提交 abb6e48f 编写于 作者: D Dong Kai 提交者: Zheng Zengkai

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 425595a7 ("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 c8ebf64e
("arm64/module: use plt section indices for relocations") to solve.
Signed-off-by: NDong Kai <dongkai11@huawei.com>
Signed-off-by: NYe Weihua <yeweihua4@huawei.com>
Reviewed-by: NYang Jihong <yangjihong1@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 2b9ee60d
......@@ -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
......
......@@ -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;
}
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册