KDB Maintainers: A bug exists in the kallsyms_symbol_next() that causes an invalid page fault. When moving to the next module (outer for-loop), the static variable ka_sym should always be updated to reference the new module's symbol table. This is only happening on the first call to this method, though. This causes ka_sym to run beyond the end of the previous module's symbol table and KDB dies when it uses a random offset into the string table of the current module.
I found this bug when trying to do tab completion on ".text". The patch is for the stock 2.4.23 source patched with the kdb-v4.3-2.4.23-common-2 and kdb-v4.3-2.4.23-i386-1. Let me know if this is helpful, or if I can provide more information. Thanks, Chris Rorvick [EMAIL PROTECTED] __________________________________ Do you Yahoo!? Yahoo! Search - Find what you�re looking for faster http://search.yahoo.com -- Attached file included as plaintext by Ecartis -- -- File: kdb-v4.3-2.4.23.patch -- Desc: kdb-v4.3-2.4.23.patch --- linux-2.4.23-kdb/kdb/kdb_io.c 2004-03-09 14:41:46.000000000 +0000 +++ linux-2.4.23-kdb-patched/kdb/kdb_io.c 2004-03-09 14:48:36.000000000 +0000 @@ -346,7 +346,7 @@ } kdb_printf("\n"); for(i=0;i<count;i++) { - if(kallsyms_symbol_next(p_tmp, i)<0) + if(kallsyms_symbol_next(p_tmp, i) == 0) break; kdb_printf("%s ",p_tmp); *(p_tmp+len)='\0'; --- linux-2.4.23-kdb/kernel/kallsyms.c 2004-03-09 14:41:46.000000000 +0000 +++ linux-2.4.23-kdb-patched/kernel/kallsyms.c 2004-03-10 03:49:41.000000000 +0000 @@ -365,7 +365,7 @@ } /* paramter prefix_name is a buffer provided by the caller, it must ends with '\0'. */ -/* parameter flag = 0 means search from the head, flag = 1 means continue search. */ +/* parameter flag = 0 means search from the head, flag != 0 means continue search. */ /* return a symbol string which matches the given prefix. */ /* return 0 means no prefix string is found. */ /* return >0 means prefix string is found. */ @@ -374,9 +374,9 @@ int flag /* Indicate if search from the head */ ) { - const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ - const char *ka_str = NULL; + static const struct kallsyms_header *ka_hdr; static const struct kallsyms_symbol *ka_sym; + static const char *ka_str; static const struct module *m; static int i; int prefix_len=strlen(prefix_name); @@ -388,22 +388,16 @@ if(!flag) { m = *kallsyms_module_list; + goto init_mod_kallsyms; } - for (; m; m = m->next) { + while (1) { if (!mod_member_present(m, kallsyms_start) || !mod_member_present(m, kallsyms_end) || m->kallsyms_start >= m->kallsyms_end) continue; - ka_hdr = (struct kallsyms_header *)m->kallsyms_start; - if(!flag) { - ka_sym = (struct kallsyms_symbol *) - ((char *)(ka_hdr) + ka_hdr->symbol_off); - i = 0; - } - ka_str = ((char *)(ka_hdr) + ka_hdr->string_off); - for (; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) { + for (; i < ka_hdr->symbols; ++i) { p = ka_str + ka_sym->name_off; if (strncmp(p, prefix_name,prefix_len) == 0) { strncpy(prefix_name, p, strlen(p)+1); @@ -411,7 +405,17 @@ kallsyms_next_sym(ka_hdr, ka_sym); return 1; } + kallsyms_next_sym(ka_hdr, ka_sym); } + + if ( (m = m->next) == NULL) + break; + +init_mod_kallsyms: + ka_hdr = (void *) (m->kallsyms_start); + ka_sym = (void *) (m->kallsyms_start + ka_hdr->symbol_off); + ka_str = (void *) (m->kallsyms_start + ka_hdr->string_off); + i = 0; } return 0; --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.
