summaryrefslogtreecommitdiffstats
path: root/sys/kern/link_elf_obj.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2001-08-10 23:15:13 +0000
committerwpaul <wpaul@FreeBSD.org>2001-08-10 23:15:13 +0000
commit69603fe5d4a5db02b03e6a8d979e6e4ecf1787a4 (patch)
tree65fc7ee5df389e3d8dc729739d518da5eaa8d65a /sys/kern/link_elf_obj.c
parentadd729e8404a84d920980fd5865f0ef019373b8b (diff)
downloadFreeBSD-src-69603fe5d4a5db02b03e6a8d979e6e4ecf1787a4.zip
FreeBSD-src-69603fe5d4a5db02b03e6a8d979e6e4ecf1787a4.tar.gz
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.
Diffstat (limited to 'sys/kern/link_elf_obj.c')
-rw-r--r--sys/kern/link_elf_obj.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 785d23a..0f6a87a 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -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;
OpenPOWER on IntegriCloud