From abb6e48faf55c3741712e8da7d1da5c9dd7764a9 Mon Sep 17 00:00:00 2001 From: Dong Kai Date: Sat, 29 May 2021 14:42:48 +0800 Subject: [PATCH] arm/module: Use plt section indices for relocations hulk inclusion category: feature bugzilla: 51921 CVE: NA --------------------------- We are planning to add livepatch without ftrace support for arm in the next commit. However after commit 425595a7fc20 ("livepatch: reuse module loader code to write relocations") merged, the klp relocations is done by apply_relocate function. The mod->arch.{core,init}.plt pointers were problematic for livepatch because they pointed within temporary section headers (provided by the module loader via info->sechdrs) that would be freed after module load. Here we take same modification based on commit c8ebf64eab74 ("arm64/module: use plt section indices for relocations") to solve. Signed-off-by: Dong Kai Signed-off-by: Ye Weihua Reviewed-by: Yang Jihong Signed-off-by: Zheng Zengkai --- arch/arm/include/asm/module.h | 5 ++-- arch/arm/kernel/module-plts.c | 43 ++++++++++++++++++++--------------- arch/arm/kernel/module.c | 4 ++-- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 4b0df09cbe67..ac3df84b935c 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -20,7 +20,7 @@ enum { #endif struct mod_plt_sec { - struct elf32_shdr *plt; + int plt_shndx; int plt_count; }; @@ -35,7 +35,8 @@ struct mod_arch_specific { }; struct module; -u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val); +u32 get_module_plt(struct module *mod, Elf32_Shdr *sechdrs, + unsigned long loc, Elf32_Addr val); #ifdef CONFIG_THUMB2_KERNEL #define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c index 6e626abaefc5..1dbdf2726505 100644 --- a/arch/arm/kernel/module-plts.c +++ b/arch/arm/kernel/module-plts.c @@ -34,12 +34,14 @@ static bool in_init(const struct module *mod, unsigned long loc) return loc - (u32)mod->init_layout.base < mod->init_layout.size; } -u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) +u32 get_module_plt(struct module *mod, Elf32_Shdr *sechdrs, + unsigned long loc, Elf32_Addr val) { struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : &mod->arch.init; - struct plt_entries *plt = (struct plt_entries *)pltsec->plt->sh_addr; + struct plt_entries *plt = + (struct plt_entries *)sechdrs[pltsec->plt_shndx].sh_addr; int idx = 0; /* @@ -60,7 +62,8 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) } pltsec->plt_count++; - BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > pltsec->plt->sh_size); + BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > + sechdrs[pltsec->plt_shndx].sh_size); if (!idx) /* Populate a new set of entries */ @@ -193,21 +196,23 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, unsigned long init_plts = 0; Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; Elf32_Sym *syms = NULL; + Elf32_Shdr *core_pltsec, *init_pltsec; + int i = 0; /* * To store the PLTs, we expand the .text section for core module code * and for initialization code. */ - for (s = sechdrs; s < sechdrs_end; ++s) { + for (s = sechdrs; s < sechdrs_end; ++s, ++i) { if (strcmp(".plt", secstrings + s->sh_name) == 0) - mod->arch.core.plt = s; + mod->arch.core.plt_shndx = i; else if (strcmp(".init.plt", secstrings + s->sh_name) == 0) - mod->arch.init.plt = s; + mod->arch.init.plt_shndx = i; else if (s->sh_type == SHT_SYMTAB) syms = (Elf32_Sym *)s->sh_addr; } - if (!mod->arch.core.plt || !mod->arch.init.plt) { + if (!mod->arch.core.plt_shndx || !mod->arch.init.plt_shndx) { pr_err("%s: module PLT section(s) missing\n", mod->name); return -ENOEXEC; } @@ -239,21 +244,23 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, numrels, s->sh_info); } - mod->arch.core.plt->sh_type = SHT_NOBITS; - mod->arch.core.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; - mod->arch.core.plt->sh_addralign = L1_CACHE_BYTES; - mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE, - sizeof(struct plt_entries)); + core_pltsec = sechdrs + mod->arch.core.plt_shndx; + core_pltsec->sh_type = SHT_NOBITS; + core_pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + core_pltsec->sh_addralign = L1_CACHE_BYTES; + core_pltsec->sh_size = round_up(core_plts * PLT_ENT_SIZE, + sizeof(struct plt_entries)); mod->arch.core.plt_count = 0; - mod->arch.init.plt->sh_type = SHT_NOBITS; - mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; - mod->arch.init.plt->sh_addralign = L1_CACHE_BYTES; - mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE, - sizeof(struct plt_entries)); + init_pltsec = sechdrs + mod->arch.init.plt_shndx; + init_pltsec->sh_type = SHT_NOBITS; + init_pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + init_pltsec->sh_addralign = L1_CACHE_BYTES; + init_pltsec->sh_size = round_up(init_plts * PLT_ENT_SIZE, + sizeof(struct plt_entries)); mod->arch.init.plt_count = 0; pr_debug("%s: plt=%x, init.plt=%x\n", __func__, - mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size); + core_pltsec->sh_size, init_pltsec->sh_size); return 0; } diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index beac45e89ba6..1cd09cf38c69 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -142,7 +142,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS) && (offset <= (s32)0xfe000000 || offset >= (s32)0x02000000)) - offset = get_module_plt(module, loc, + offset = get_module_plt(module, sechdrs, loc, offset + loc + 8) - loc - 8; @@ -265,7 +265,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS) && (offset <= (s32)0xff000000 || offset >= (s32)0x01000000)) - offset = get_module_plt(module, loc, + offset = get_module_plt(module, sechdrs, loc, offset + loc + 4) - loc - 4; -- GitLab