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:
Bill Paul 2001-08-10 23:15:13 +00:00
parent eb1d91d1c9
commit c214e6636e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=81500
2 changed files with 28 additions and 4 deletions

View file

@ -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;

View file

@ -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;