Re: Crash loading dtraceall

From: Mark Johnston <markj_at_freebsd.org>
Date: Wed, 8 May 2019 23:32:11 -0400
On Wed, May 08, 2019 at 05:57:18PM -0500, Larry Rosenman wrote:
> On 05/08/2019 5:55 pm, Mark Johnston wrote:
> > On Wed, May 08, 2019 at 05:47:08PM -0500, Larry Rosenman wrote:
> >> On 05/08/2019 5:29 pm, Mark Johnston wrote:
> >> > On Wed, May 08, 2019 at 03:52:45PM -0500, Larry Rosenman wrote:
> >> >> Greetings,
> >> >>
> >> >>     Somewhere between r346483 and r347241 loading dtraceall causes a
> >> >>     crash.  I have the cores and kernels.
> >> >>
> >> >>     It's hard for me to bisect more than this, as the box is remote.
> >> >>
> >> >>     What more do you need?  (this dump is fropm r347355).
> >> >
> >> > Please visit frame 8 and print *lf.
> >> >
> >> #9  fbt_provide_module_function (lf=0xfffff800020ff000, symindx=30763,
> >> symval=0xfffffe00d74d7e00, opaque=0xfffffe00d74d7e50) at
> >> /usr/src/sys/cddl/dev/fbt/x86/fbt_isa.c:191
> >> 191			if (*instr == FBT_PUSHL_EBP)
> >> (kgdb) print *lf
> >> $1 = {ops = 0xfffff800020f6000, refs = 202, userrefs = 1, flags = 1,
> >> link = {tqe_next = 0xfffff800020fec00, tqe_prev = 0xffffffff80c767d0
> >> <linker_files>}, filename = 0xfffff80002101030 "kernel",
> >>    pathname = 0xfffff80002104080 "/boot/kernel/kernel", id = 1, 
> >> address =
> >> 0xffffffff80200000 "\177ELF\002\001\001\t", size = 17612816, 
> >> ctors_addr
> >> = 0x0, ctors_size = 0, ndeps = 0, deps = 0x0, common = {stqh_first =
> >> 0x0,
> >>      stqh_last = 0xfffff800020ff070}, modules = {tqh_first =
> >> 0xfffff800020e5800, tqh_last = 0xfffff80002116790}, loaded = {tqe_next 
> >> =
> >> 0x0, tqe_prev = 0x0}, loadcnt = 1, nenabled = 0, fbt_nentries = 25062}
> >> (kgdb)
> > 
> > And could you show the output of:
> > 
> > $ readelf -s /boot/kernel/kernel | grep "30763:"
> > _______________________________________________
> > freebsd-current_at_freebsd.org mailing list
> > https://lists.freebsd.org/mailman/listinfo/freebsd-current
> > To unsubscribe, send any mail to 
> > "freebsd-current-unsubscribe_at_freebsd.org"
> 
> [root_at_oldtbh2 /var/crash]# readelf -s /boot/kernel/kernel | grep 
> "30763:"
>   30763: ffffffff80791310    75 IFUNC   GLOBAL DEFAULT    8 x86_rng_store
> [root_at_oldtbh2 /var/crash]#

The problem is with the kernel linker's handling of ifuncs.  When
enumerating symbols, it replaces ifunc symbol values with the return
value of the resolver but preserves the original symbol size, which is
that of the resolver.  I believe this patch will address the panic
you're seeing:

diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index 6ceb34d66b74..8bd9a0219a1d 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
_at__at_ -1350,17 +1350,23 _at__at_ static int
 link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
     linker_symval_t *symval)
 {
+	c_linker_sym_t target;
 	elf_file_t ef;
 	const Elf_Sym *es;
 	caddr_t val;
+	long diff;
 
 	ef = (elf_file_t)lf;
 	es = (const Elf_Sym *)sym;
 	if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) {
 		symval->name = ef->strtab + es->st_name;
 		val = (caddr_t)ef->address + es->st_value;
-		if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
+		if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) {
 			val = ((caddr_t (*)(void))val)();
+			(void)link_elf_search_symbol(lf, val, &target, &diff);
+			if (diff == 0)
+				es = (const Elf_Sym *)target;
+		}
 		symval->value = val;
 		symval->size = es->st_size;
 		return (0);
_at__at_ -1370,8 +1376,12 _at__at_ link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
 	if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
 		symval->name = ef->ddbstrtab + es->st_name;
 		val = (caddr_t)ef->address + es->st_value;
-		if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
+		if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) {
 			val = ((caddr_t (*)(void))val)();
+			(void)link_elf_search_symbol(lf, val, &target, &diff);
+			if (diff == 0)
+				es = (const Elf_Sym *)target;
+		}
 		symval->value = val;
 		symval->size = es->st_size;
 		return (0);
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index ac4cc8c085cb..5ce160a05699 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
_at__at_ -1240,9 +1240,11 _at__at_ static int
 link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
     linker_symval_t *symval)
 {
+	c_linker_sym_t target;
 	elf_file_t ef;
 	const Elf_Sym *es;
 	caddr_t val;
+	long diff;
 
 	ef = (elf_file_t) lf;
 	es = (const Elf_Sym*) sym;
_at__at_ -1250,8 +1252,12 _at__at_ link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
 	if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) {
 		symval->name = ef->ddbstrtab + es->st_name;
 		val = (caddr_t)es->st_value;
-		if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
+		if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) {
 			val = ((caddr_t (*)(void))val)();
+			(void)link_elf_search_symbol(lf, val, &target, &diff);
+			if (diff == 0)
+				es = (const Elf_Sym *)target;
+		}
 		symval->value = val;
 		symval->size = es->st_size;
 		return 0;
Received on Thu May 09 2019 - 01:32:17 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:20 UTC