Skip to content

Commit 99e729b

Browse files
Sergei Trofimovichtorvalds
Sergei Trofimovich
authored andcommitted
ia64: module: fix symbolizer crash on fdescr
Noticed failure as a crash on ia64 when tried to symbolize all backtraces collected by page_owner=on: $ cat /sys/kernel/debug/page_owner <oops> CPU: 1 PID: 2074 Comm: cat Not tainted 5.12.0-rc4 #226 Hardware name: hp server rx3600, BIOS 04.03 04/08/2008 ip is at dereference_module_function_descriptor+0x41/0x100 Crash happens at dereference_module_function_descriptor() due to use-after-free when dereferencing ".opd" section header. All section headers are already freed after module is laoded successfully. To keep symbolizer working the change stores ".opd" address and size after module is relocated to a new place and before section headers are discarded. To make similar errors less obscure module_finalize() now zeroes out all variables relevant to module loading only. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Sergei Trofimovich <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 9187592 commit 99e729b

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

arch/ia64/include/asm/module.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,20 @@
1414
struct elf64_shdr; /* forward declration */
1515

1616
struct mod_arch_specific {
17+
/* Used only at module load time. */
1718
struct elf64_shdr *core_plt; /* core PLT section */
1819
struct elf64_shdr *init_plt; /* init PLT section */
1920
struct elf64_shdr *got; /* global offset table */
2021
struct elf64_shdr *opd; /* official procedure descriptors */
2122
struct elf64_shdr *unwind; /* unwind-table section */
2223
unsigned long gp; /* global-pointer for module */
24+
unsigned int next_got_entry; /* index of next available got entry */
2325

26+
/* Used at module run and cleanup time. */
2427
void *core_unw_table; /* core unwind-table cookie returned by unwinder */
2528
void *init_unw_table; /* init unwind-table cookie returned by unwinder */
26-
unsigned int next_got_entry; /* index of next available got entry */
29+
void *opd_addr; /* symbolize uses .opd to get to actual function */
30+
unsigned long opd_size;
2731
};
2832

2933
#define ARCH_SHF_SMALL SHF_IA_64_SHORT

arch/ia64/kernel/module.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,31 @@ register_unwind_table (struct module *mod)
905905
int
906906
module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod)
907907
{
908+
struct mod_arch_specific *mas = &mod->arch;
909+
908910
DEBUGP("%s: init: entry=%p\n", __func__, mod->init);
909-
if (mod->arch.unwind)
911+
if (mas->unwind)
910912
register_unwind_table(mod);
913+
914+
/*
915+
* ".opd" was already relocated to the final destination. Store
916+
* it's address for use in symbolizer.
917+
*/
918+
mas->opd_addr = (void *)mas->opd->sh_addr;
919+
mas->opd_size = mas->opd->sh_size;
920+
921+
/*
922+
* Module relocation was already done at this point. Section
923+
* headers are about to be deleted. Wipe out load-time context.
924+
*/
925+
mas->core_plt = NULL;
926+
mas->init_plt = NULL;
927+
mas->got = NULL;
928+
mas->opd = NULL;
929+
mas->unwind = NULL;
930+
mas->gp = 0;
931+
mas->next_got_entry = 0;
932+
911933
return 0;
912934
}
913935

@@ -926,10 +948,9 @@ module_arch_cleanup (struct module *mod)
926948

927949
void *dereference_module_function_descriptor(struct module *mod, void *ptr)
928950
{
929-
Elf64_Shdr *opd = mod->arch.opd;
951+
struct mod_arch_specific *mas = &mod->arch;
930952

931-
if (ptr < (void *)opd->sh_addr ||
932-
ptr >= (void *)(opd->sh_addr + opd->sh_size))
953+
if (ptr < mas->opd_addr || ptr >= mas->opd_addr + mas->opd_size)
933954
return ptr;
934955

935956
return dereference_function_descriptor(ptr);

0 commit comments

Comments
 (0)