Fix some of the GDB linkage setup. The l_name member of the gdb linkage
structure is always free()ed yet only sometimes malloc()ed. In particular, it was simply set to point to l_filename from the a linker_file_t in link_elf_link_preload_finish(). The l_filename had been malloc()ed inside the kern_linker.c module and was being free()ed twice: once by link_elf_unload_file() and again by linker_file_unload(), leading to a panic. How to duplicate the problem: - Pre-load a kernel module from the loader, i.e. if_sis.ko - Boot system - Attempt to unload module with kldunload if_sis - Bewm The problem here is that the case where the module was loaded with kldload after system boot would work correctly, so this bug went unnoticed until I stubbed my toe on it just now. (Also, you can only trip this bug if you compile a kernel with options DDB, but that's the default now.) Fix: remember to malloc() a separate copy of the module name for the l_name member of the gdb linkage structure in three places where the linkage structure can be initialized.
This commit is contained in:
parent
eb1d91d1c9
commit
c214e6636e
@ -173,6 +173,9 @@ link_elf_init(void* arg)
|
||||
caddr_t modptr, baseptr, sizeptr;
|
||||
elf_file_t ef;
|
||||
char *modname;
|
||||
#ifdef DDB
|
||||
char *newfilename;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
linker_add_class(&link_elf_class);
|
||||
@ -219,7 +222,9 @@ link_elf_init(void* arg)
|
||||
|
||||
#ifdef DDB
|
||||
ef->gdb.l_addr = linker_kernel_file->address;
|
||||
ef->gdb.l_name = modname;
|
||||
newfilename = malloc(strlen(modname) + 1, M_LINKER, M_WAITOK);
|
||||
strcpy(newfilename, modname);
|
||||
ef->gdb.l_name = newfilename;
|
||||
ef->gdb.l_ld = dp;
|
||||
ef->gdb.l_prev = 0;
|
||||
ef->gdb.l_next = 0;
|
||||
@ -473,6 +478,9 @@ link_elf_link_preload_finish(linker_file_t lf)
|
||||
{
|
||||
elf_file_t ef;
|
||||
int error;
|
||||
#ifdef DDB
|
||||
char *newfilename;
|
||||
#endif
|
||||
|
||||
ef = (elf_file_t) lf;
|
||||
#if 0 /* this will be more trouble than it's worth for now */
|
||||
@ -493,7 +501,9 @@ link_elf_link_preload_finish(linker_file_t lf)
|
||||
#ifdef DDB
|
||||
GDB_STATE(RT_ADD);
|
||||
ef->gdb.l_addr = lf->address;
|
||||
ef->gdb.l_name = lf->filename;
|
||||
newfilename = malloc(strlen(lf->filename) + 1, M_LINKER, M_WAITOK);
|
||||
strcpy(newfilename, lf->filename);
|
||||
ef->gdb.l_name = newfilename;
|
||||
ef->gdb.l_ld = ef->dynamic;
|
||||
link_elf_add_gdb(&ef->gdb);
|
||||
GDB_STATE(RT_CONSISTENT);
|
||||
@ -530,7 +540,9 @@ link_elf_load_file(linker_class_t cls, const char* filename, linker_file_t* resu
|
||||
int symstrindex;
|
||||
int symcnt;
|
||||
int strcnt;
|
||||
#ifdef DDB
|
||||
char *newfilename;
|
||||
#endif
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
|
@ -173,6 +173,9 @@ link_elf_init(void* arg)
|
||||
caddr_t modptr, baseptr, sizeptr;
|
||||
elf_file_t ef;
|
||||
char *modname;
|
||||
#ifdef DDB
|
||||
char *newfilename;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
linker_add_class(&link_elf_class);
|
||||
@ -219,7 +222,9 @@ link_elf_init(void* arg)
|
||||
|
||||
#ifdef DDB
|
||||
ef->gdb.l_addr = linker_kernel_file->address;
|
||||
ef->gdb.l_name = modname;
|
||||
newfilename = malloc(strlen(modname) + 1, M_LINKER, M_WAITOK);
|
||||
strcpy(newfilename, modname);
|
||||
ef->gdb.l_name = newfilename;
|
||||
ef->gdb.l_ld = dp;
|
||||
ef->gdb.l_prev = 0;
|
||||
ef->gdb.l_next = 0;
|
||||
@ -473,6 +478,9 @@ link_elf_link_preload_finish(linker_file_t lf)
|
||||
{
|
||||
elf_file_t ef;
|
||||
int error;
|
||||
#ifdef DDB
|
||||
char *newfilename;
|
||||
#endif
|
||||
|
||||
ef = (elf_file_t) lf;
|
||||
#if 0 /* this will be more trouble than it's worth for now */
|
||||
@ -493,7 +501,9 @@ link_elf_link_preload_finish(linker_file_t lf)
|
||||
#ifdef DDB
|
||||
GDB_STATE(RT_ADD);
|
||||
ef->gdb.l_addr = lf->address;
|
||||
ef->gdb.l_name = lf->filename;
|
||||
newfilename = malloc(strlen(lf->filename) + 1, M_LINKER, M_WAITOK);
|
||||
strcpy(newfilename, lf->filename);
|
||||
ef->gdb.l_name = newfilename;
|
||||
ef->gdb.l_ld = ef->dynamic;
|
||||
link_elf_add_gdb(&ef->gdb);
|
||||
GDB_STATE(RT_CONSISTENT);
|
||||
@ -530,7 +540,9 @@ link_elf_load_file(linker_class_t cls, const char* filename, linker_file_t* resu
|
||||
int symstrindex;
|
||||
int symcnt;
|
||||
int strcnt;
|
||||
#ifdef DDB
|
||||
char *newfilename;
|
||||
#endif
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user