Linux process causes kernel panic

Konstantin Belousov kostikbel at gmail.com
Mon Aug 6 20:37:50 UTC 2018


On Mon, Aug 06, 2018 at 06:24:43PM +0300, Vladimir Kondratyev wrote:
> I've got similar panic right after skype start
> 
> Disabling of SMAP via loader tunable workarounded the panic for me.
> 
> Applying of the patch make skype eating 100%CPU in unkillable state.
> 
> tail of ktrace dump
> 
>   1238 skype    CALL  linux_gettid
>   1238 skype    RET   linux_gettid 101123/0x18b03
>   1238 skype    CALL 
> linux_sys_futex(0x3301edc,0x84,0x1,0x7fffffff,0x3301ec0,0x2)
>   1238 skype    RET   linux_sys_futex 0
>   1238 skype    CALL  linux_sys_futex(0x33b0fac,0x80,0x1,0,0x33b0f90,0x1)
>   1238 skype    CALL  linux_sys_futex(0x3301edc,0x80,0x1,0,0x3301ec0,0x1)
>   1238 skype    RET   linux_sys_futex -1 errno -11 Resource temporarily
> unavailable
>   1238 skype    CALL 
> linux_sys_futex(0x3301ec0,0x81,0x1,0x3301ec0,0x33b02c8,0xffffc168)
>   1238 skype    RET   linux_sys_futex 0
>   1238 skype    CALL 
> linux_sys_futex(0x33b0fac,0x85,0x1,0x1,0x33b0fa8,0x4000001)
> -- here it stops --
Can you fix your mail client ?

> ddb also shows that process is looping somewhere inside linux_sys_futex()

There are two bugs.  One is that ifuncs handling for relocations against
local symbols in elf obj modules was missed.  Patch below fixed it for me.

Second bug is that futexes seems to not handle accesses to the CoW
mappings which are not yet copied.  I think that the second bug is
irrelevant for your case, since it worked before.

Try this patch in addition to the linux/ patches I sent before.

diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 43f85bd17c9..872cb79f38b 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -142,7 +142,7 @@ static int	link_elf_each_function_name(linker_file_t,
 static int	link_elf_each_function_nameval(linker_file_t,
 				linker_function_nameval_callback_t,
 				void *);
-static int	link_elf_reloc_local(linker_file_t);
+static int	link_elf_reloc_local(linker_file_t, bool);
 static long	link_elf_symtab_get(linker_file_t, const Elf_Sym **);
 static long	link_elf_strtab_get(linker_file_t, caddr_t *);
 
@@ -441,7 +441,10 @@ link_elf_link_preload(linker_class_t cls, const char *filename,
 	}
 
 	/* Local intra-module relocations */
-	error = link_elf_reloc_local(lf);
+	error = link_elf_reloc_local(lf, false);
+	if (error != 0)
+		goto out;
+	error = link_elf_reloc_local(lf, true);
 	if (error != 0)
 		goto out;
 
@@ -969,7 +972,7 @@ link_elf_load_file(linker_class_t cls, const char *filename,
 	}
 
 	/* Local intra-module relocations */
-	error = link_elf_reloc_local(lf);
+	error = link_elf_reloc_local(lf, false);
 	if (error != 0)
 		goto out;
 
@@ -985,6 +988,11 @@ link_elf_load_file(linker_class_t cls, const char *filename,
 	if (error)
 		goto out;
 
+	/* Now ifuncs. */
+	error = link_elf_reloc_local(lf, true);
+	if (error != 0)
+		goto out;
+
 	/* Notify MD code that a module is being loaded. */
 	error = elf_cpu_load_file(lf);
 	if (error)
@@ -1374,7 +1382,10 @@ elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *res)
 
 	/* Quick answer if there is a definition included. */
 	if (sym->st_shndx != SHN_UNDEF) {
-		*res = sym->st_value;
+		res1 = (Elf_Addr)sym->st_value;
+		if (ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC)
+			res1 = ((Elf_Addr (*)(void))res1)();
+		*res = res1;
 		return (0);
 	}
 
@@ -1470,7 +1481,7 @@ link_elf_fix_link_set(elf_file_t ef)
 }
 
 static int
-link_elf_reloc_local(linker_file_t lf)
+link_elf_reloc_local(linker_file_t lf, bool ifuncs)
 {
 	elf_file_t ef = (elf_file_t)lf;
 	const Elf_Rel *rellim;
@@ -1505,8 +1516,13 @@ link_elf_reloc_local(linker_file_t lf)
 			/* Only do local relocs */
 			if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
 				continue;
-			elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
-			    elf_obj_lookup);
+			if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) ==
+			    ifuncs)
+				elf_reloc_local(lf, base, rel, ELF_RELOC_REL,
+				    elf_obj_lookup);
+			else if (ifuncs)
+				elf_reloc_ifunc(lf, base, rel, ELF_RELOC_REL,
+				    elf_obj_lookup);
 		}
 	}
 
@@ -1531,8 +1547,13 @@ link_elf_reloc_local(linker_file_t lf)
 			/* Only do local relocs */
 			if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
 				continue;
-			elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
-			    elf_obj_lookup);
+			if ((ELF_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) ==
+			    ifuncs)
+				elf_reloc_local(lf, base, rela, ELF_RELOC_RELA,
+				    elf_obj_lookup);
+			else if (ifuncs)
+				elf_reloc_ifunc(lf, base, rela, ELF_RELOC_RELA,
+				    elf_obj_lookup);
 		}
 	}
 	return (0);


More information about the freebsd-current mailing list