提交 716653dd 编写于 作者: C Cheng Jian 提交者: Xie XiuQi

livepatch/arm64: support livepatch emit plt call

euler inclusion
category: feature
Bugzilla: 5507
CVE: N/A

----------------------------------------

The livepatch without ftrace mode uses the direct jump method to
implement the livepatch. When KASLR is enabled, the address of the
symbol which need relocate in the module may exceeds the range of
short jump. In the module, this is implemented by the PLT sections.

In previous versions, kpatch-build front-tools
create an section named livepatch.pltcount to store the number of
the relocations in the size field, we append enough space in .plt
section for the long jump plts by module_frob_arch_sections. Now,
This's no longer needed.

The .klp.rela.objname.secname section store all symbols that required
relocate by livepatch. For commit 425595a7 ("livepatch: reuse
module loader code to write relocations") merged, load_module can
create enough plt entries for livepatch by module_frob_arch_sections.
we will fix it soon.
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
Reviewed-by: NLi Bin <huawei.libin@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 5aa9a1a3
......@@ -33,6 +33,11 @@ struct mod_arch_specific {
/* for CONFIG_DYNAMIC_FTRACE */
struct plt_entry *ftrace_trampoline;
#ifdef CONFIG_LIVEPATCH
struct plt_entry *core_plts;
bool have_plts;
#endif
};
#endif
......@@ -41,6 +46,9 @@ u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela *rela,
u64 module_emit_veneer_for_adrp(struct module *mod, void *loc, u64 val);
u64 livepatch_emit_plt_entry(struct module *mod, void *loc,
const Elf64_Rela *rela, Elf64_Sym *sym);
#ifdef CONFIG_RANDOMIZE_BASE
extern u64 module_alloc_base;
#else
......
......@@ -42,6 +42,48 @@ u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela *rela,
return (u64)&plt[i];
}
#ifdef CONFIG_LIVEPATCH
void klp_get_core_plts(struct module *mod)
{
if (is_livepatch_module(mod) && mod->arch.have_plts)
mod->arch.core_plts = (struct plt_entry *)
mod->arch.core.plt->sh_addr;
}
u64 livepatch_emit_plt_entry(struct module *mod, void *loc,
const Elf64_Rela *rela, Elf64_Sym *sym)
{
struct mod_plt_sec *pltsec = &mod->arch.core;
struct plt_entry *plt = (struct plt_entry *)mod->arch.core_plts;
int i = pltsec->plt_num_entries;
u64 val = sym->st_value + rela->r_addend;
plt[i] = get_plt_entry(val);
/*
* Check if the entry we just created is a duplicate. Given that the
* relocations are sorted, this will be the last entry we allocated.
* (if one exists).
*/
if (i > 0 && plt_entries_equal(plt + i, plt + i - 1))
return (u64)&plt[i - 1];
pltsec->plt_num_entries++;
if (WARN_ON(pltsec->plt_num_entries > pltsec->plt_max_entries))
return 0;
return (u64)&plt[i];
}
#else
u64 livepatch_emit_plt_entry(struct module *mod, void *loc,
const Elf64_Rela *rela, Elf64_Sym *sym)
{
WARN(1, "Live patching support is disabled, but catch SHF_RELA_LIVEPATCH relocation\n");
return 0;
}
#endif /* #ifdef CONFIG_LIVEPATCH */
#ifdef CONFIG_ARM64_ERRATUM_843419
u64 module_emit_veneer_for_adrp(struct module *mod, void *loc, u64 val)
{
......@@ -265,6 +307,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
break;
}
}
if (mod->arch.core.plt)
mod->arch.have_plts = true;
mod->arch.core_plts = NULL;
#endif
mod->arch.core.plt->sh_type = SHT_NOBITS;
......
......@@ -413,7 +413,13 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
ovf == -ERANGE) {
val = module_emit_plt_entry(me, loc, &rel[i], sym);
if (!(sechdrs[relsec].sh_flags
& SHF_RELA_LIVEPATCH))
val = module_emit_plt_entry(me,
loc, &rel[i], sym);
else
val = livepatch_emit_plt_entry(me,
loc, &rel[i], sym);
if (!val)
return -ENOEXEC;
ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2,
......
......@@ -2036,6 +2036,10 @@ static void module_disable_nx(const struct module *mod) { }
#endif
#ifdef CONFIG_LIVEPATCH
void __weak klp_get_core_plts(struct module *mod)
{
}
/*
* Persist Elf information about a module. Copy the Elf header,
* section header table, section string table, and symtab section
......@@ -2084,6 +2088,8 @@ static int copy_module_elf(struct module *mod, struct load_info *info)
mod->klp_info->sechdrs[symndx].sh_addr = \
(unsigned long) mod->core_kallsyms.symtab;
klp_get_core_plts(mod);
return 0;
free_sechdrs:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册