From: Petr Mladek <pmladek@suse.com>
To: Song Liu <song@kernel.org>
Cc: live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
jpoimboe@kernel.org, jikos@kernel.org, mbenes@suse.cz,
x86@kernel.org, joe.lawrence@redhat.com,
linuxppc-dev@lists.ozlabs.org,
Josh Poimboeuf <jpoimboe@redhat.com>
Subject: Re: [PATCH v6] livepatch: Clear relocation targets on a module removal
Date: Fri, 18 Nov 2022 17:24:04 +0100 [thread overview]
Message-ID: <Y3expGRt4cPoZgHL@alley> (raw)
In-Reply-To: <20220901171252.2148348-1-song@kernel.org>
On Thu 2022-09-01 10:12:52, Song Liu wrote:
> From: Miroslav Benes <mbenes@suse.cz>
>
> Josh reported a bug:
>
> When the object to be patched is a module, and that module is
> rmmod'ed and reloaded, it fails to load with:
>
> module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 2, loc 00000000ba0302e9, val ffffffffa03e293c
> livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
> livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'
>
> The livepatch module has a relocation which references a symbol
> in the _previous_ loading of nfsd. When apply_relocate_add()
> tries to replace the old relocation with a new one, it sees that
> the previous one is nonzero and it errors out.
>
> We thus decided to reverse the relocation patching (clear all relocation
> targets on x86_64). The solution is not
> universal and is too much arch-specific, but it may prove to be simpler
> in the end.
>
> arch/powerpc/kernel/module_32.c | 10 ++++
> arch/powerpc/kernel/module_64.c | 49 +++++++++++++++
> arch/s390/kernel/module.c | 8 +++
> arch/x86/kernel/module.c | 102 +++++++++++++++++++++++---------
> include/linux/moduleloader.h | 7 +++
> kernel/livepatch/core.c | 41 ++++++++++++-
First, thanks a lot for working on this.
I can't check or test the powerpc and s390 code easily.
I am going to comment only x86 and generic code. It looks good
but it needs some changes to improve maintainability.
> 6 files changed, 189 insertions(+), 28 deletions(-)
>
> diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
> index ea6536171778..e3c312770453 100644
> --- a/arch/powerpc/kernel/module_32.c
> +++ b/arch/powerpc/kernel/module_32.c
> @@ -285,6 +285,16 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
> return 0;
> }
>
> +#ifdef CONFIG_LIVEPATCH
> +void clear_relocate_add(Elf32_Shdr *sechdrs,
> + const char *strtab,
> + unsigned int symindex,
> + unsigned int relsec,
> + struct module *me)
> +{
> +}
> +#endif
> +
> #ifdef CONFIG_DYNAMIC_FTRACE
> notrace int module_trampoline_target(struct module *mod, unsigned long addr,
> unsigned long *target)
> diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
> index 7e45dc98df8a..514951f97391 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -739,6 +739,55 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
> return 0;
> }
>
> +#ifdef CONFIG_LIVEPATCH
> +void clear_relocate_add(Elf64_Shdr *sechdrs,
> + const char *strtab,
> + unsigned int symindex,
> + unsigned int relsec,
> + struct module *me)
> +{
> + unsigned int i;
> + Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
> + Elf64_Sym *sym;
> + unsigned long *location;
> + const char *symname;
> + u32 *instruction;
> +
> + pr_debug("Clearing ADD relocate section %u to %u\n", relsec,
> + sechdrs[relsec].sh_info);
> +
> + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
> + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
> + + rela[i].r_offset;
> + sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
> + + ELF64_R_SYM(rela[i].r_info);
> + symname = me->core_kallsyms.strtab
> + + sym->st_name;
> +
> + if (ELF64_R_TYPE(rela[i].r_info) != R_PPC_REL24)
> + continue;
> + /*
> + * reverse the operations in apply_relocate_add() for case
> + * R_PPC_REL24.
> + */
> + if (sym->st_shndx != SHN_UNDEF &&
> + sym->st_shndx != SHN_LIVEPATCH)
> + continue;
> +
> + instruction = (u32 *)location;
> + if (is_mprofile_ftrace_call(symname))
> + continue;
> +
> + if (!instr_is_relative_link_branch(ppc_inst(*instruction)))
> + continue;
> +
> + instruction += 1;
> + patch_instruction(instruction, ppc_inst(PPC_RAW_NOP()));
> + }
> +
> +}
This looks like a lot of duplicated code. Isn't it?
> +#endif
> +
> #ifdef CONFIG_DYNAMIC_FTRACE
> int module_trampoline_target(struct module *mod, unsigned long addr,
> unsigned long *target)
> --- a/arch/x86/kernel/module.c
> +++ b/arch/x86/kernel/module.c
> @@ -128,18 +128,20 @@ int apply_relocate(Elf32_Shdr *sechdrs,
> return 0;
> }
> #else /*X86_64*/
> -static int __apply_relocate_add(Elf64_Shdr *sechdrs,
> +static int __apply_clear_relocate_add(Elf64_Shdr *sechdrs,
Nit: Honestly, the combination of 4 verbs: "apply", "clear, "relocate", and "add"
is really crazy. It is far from obvious what the function does.
The name was not ideal even before. Let's not make it worse and
use on 3 verbs again.
What about __update_relocate_add or __write_relocate_add()?
Note that the "__" prefix is still needed, see below.
> const char *strtab,
> unsigned int symindex,
> unsigned int relsec,
> struct module *me,
> - void *(*write)(void *dest, const void *src, size_t len))
> + void *(*write)(void *dest, const void *src, size_t len),
> + bool clear)
> {
> unsigned int i;
> Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
> Elf64_Sym *sym;
> void *loc;
> u64 val;
> + u64 zero = 0ULL;
>
> DEBUGP("Applying relocate section %u to %u\n",
> relsec, sechdrs[relsec].sh_info);
> @@ -163,40 +165,60 @@ static int __apply_relocate_add(Elf64_Shdr *sechdrs,
> case R_X86_64_NONE:
> break;
> case R_X86_64_64:
> - if (*(u64 *)loc != 0)
> - goto invalid_relocation;
> - write(loc, &val, 8);
> + if (!clear) {
Nit: I would prefer to use positive check when both if/else branches
are used. I would call the parameter "apply".
> + if (*(u64 *)loc != 0)
> + goto invalid_relocation;
> + write(loc, &val, 8);
> + } else {
> + write(loc, &zero, 8);
> + }
> break;
> case R_X86_64_32:
> - if (*(u32 *)loc != 0)
> - goto invalid_relocation;
> - write(loc, &val, 4);
> - if (val != *(u32 *)loc)
> - goto overflow;
> + if (!clear) {
> + if (*(u32 *)loc != 0)
> + goto invalid_relocation;
> + write(loc, &val, 4);
> + if (val != *(u32 *)loc)
> + goto overflow;
> + } else {
> + write(loc, &zero, 4);
> + }
> break;
> case R_X86_64_32S:
> - if (*(s32 *)loc != 0)
> - goto invalid_relocation;
> - write(loc, &val, 4);
> - if ((s64)val != *(s32 *)loc)
> - goto overflow;
> + if (!clear) {
> + if (*(s32 *)loc != 0)
> + goto invalid_relocation;
> + write(loc, &val, 4);
> + if ((s64)val != *(s32 *)loc)
> + goto overflow;
> + } else {
> + write(loc, &zero, 4);
> + }
> break;
> case R_X86_64_PC32:
> case R_X86_64_PLT32:
> - if (*(u32 *)loc != 0)
> - goto invalid_relocation;
> - val -= (u64)loc;
> - write(loc, &val, 4);
> + if (!clear) {
> + if (*(u32 *)loc != 0)
> + goto invalid_relocation;
> + val -= (u64)loc;
> + write(loc, &val, 4);
> #if 0
> - if ((s64)val != *(s32 *)loc)
> - goto overflow;
> + if ((s64)val != *(s32 *)loc)
> + goto overflow;
> #endif
> + } else {
> + write(loc, &zero, 4);
> + }
> break;
> case R_X86_64_PC64:
> - if (*(u64 *)loc != 0)
> - goto invalid_relocation;
> - val -= (u64)loc;
> - write(loc, &val, 8);
> + if (!clear) {
> + if (*(u64 *)loc != 0)
> + goto invalid_relocation;
> + val -= (u64)loc;
> + write(loc, &val, 8);
> + } else {
> + write(loc, &zero, 8);
> + }
> break;
> default:
> pr_err("%s: Unknown rela relocation: %llu\n",
> @@ -245,6 +267,32 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
> return ret;
> }
>
> +#ifdef CONFIG_LIVEPATCH
> +
> +void clear_relocate_add(Elf64_Shdr *sechdrs,
> + const char *strtab,
> + unsigned int symindex,
> + unsigned int relsec,
> + struct module *me)
> +{
> + bool early = me->state == MODULE_STATE_UNFORMED;
> + void *(*write)(void *, const void *, size_t) = memcpy;
> +
> + if (!early) {
> + write = text_poke;
> + mutex_lock(&text_mutex);
> + }
> +
> + __apply_clear_relocate_add(sechdrs, strtab, symindex, relsec, me,
> + write, true /* clear */);
> +
> + if (!early) {
> + text_poke_sync();
> + mutex_unlock(&text_mutex);
> + }
> +}
This duplicates a lot of code. Please, rename apply_relocate_add() the
same way as __apply_clear_relocate_add() and add the "apply" parameter.
Then add the wrappers for this:
int write_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me,
bool apply)
{
int ret;
bool early = me->state == MODULE_STATE_UNFORMED;
void *(*write)(void *, const void *, size_t) = memcpy;
if (!early) {
write = text_poke;
mutex_lock(&text_mutex);
}
ret = __write_relocate_add(sechdrs, strtab, symindex, relsec, me,
write, apply);
if (!early) {
text_poke_sync();
mutex_unlock(&text_mutex);
}
return ret;
}
int apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
return write_relocate_add(sechdrs, strtab, symindex, relsec, me, true);
}
#ifdef CONFIG_LIVEPATCH
void apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
write_relocate_add(sechdrs, strtab, symindex, relsec, me, false);
}
#endif
> +#endif
> +
> #endif
>
> int module_finalize(const Elf_Ehdr *hdr,
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -316,6 +316,45 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
> return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod);
> }
>
> +static void klp_clear_object_relocations(struct module *pmod,
> + struct klp_object *obj)
> +{
> + int i, cnt;
> + const char *objname, *secname;
> + char sec_objname[MODULE_NAME_LEN];
> + Elf_Shdr *sec;
> +
> + objname = klp_is_module(obj) ? obj->name : "vmlinux";
> +
> + /* For each klp relocation section */
> + for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) {
> + sec = pmod->klp_info->sechdrs + i;
> + secname = pmod->klp_info->secstrings + sec->sh_name;
> + if (!(sec->sh_flags & SHF_RELA_LIVEPATCH))
> + continue;
> +
> + /*
> + * Format: .klp.rela.sec_objname.section_name
> + * See comment in klp_resolve_symbols() for an explanation
> + * of the selected field width value.
> + */
> + secname = pmod->klp_info->secstrings + sec->sh_name;
> + cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname);
> + if (cnt != 1) {
> + pr_err("section %s has an incorrectly formatted name\n",
> + secname);
> + continue;
> + }
> +
> + if (strcmp(objname, sec_objname))
> + continue;
> +
> + clear_relocate_add(pmod->klp_info->sechdrs,
> + pmod->core_kallsyms.strtab,
> + pmod->klp_info->symndx, i, pmod);
> + }
> +}
Huh, this duplicates a lot of tricky code.
It is even worse because this squashed code from two functions
klp_apply_section_relocs() and klp_apply_object_relocs()
into a single function. As a result, the code duplication is not
even obvious.
Also the suffix "_reloacations() does not match the suffix of
the related funciton:
+ klp_apply_object_relocs() (existing)
+ klp_clear_object_relocations() (new)
This all would complicate maintenance of the code.
Please, implement a common:
int klp_write_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
const char *shstrtab, const char *strtab,
unsigned int symndx, unsigned int secndx,
const char *objname, bool apply);
and
int klp_write_object_relocs(struct klp_patch *patch,
struct klp_object *obj,
bool apply);
and add the respective wrappers:
int klp_apply_section_relocs(); /* also needed in module/main.c */
int klp_apply_object_relocs();
void klp_clear_object_relocs();
Best Regards,
Petr
WARNING: multiple messages have this Message-ID (diff)
From: Petr Mladek <pmladek@suse.com>
To: Song Liu <song@kernel.org>
Cc: jikos@kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org,
joe.lawrence@redhat.com, Josh Poimboeuf <jpoimboe@redhat.com>,
live-patching@vger.kernel.org, mbenes@suse.cz,
linuxppc-dev@lists.ozlabs.org, jpoimboe@kernel.org
Subject: Re: [PATCH v6] livepatch: Clear relocation targets on a module removal
Date: Fri, 18 Nov 2022 17:24:04 +0100 [thread overview]
Message-ID: <Y3expGRt4cPoZgHL@alley> (raw)
In-Reply-To: <20220901171252.2148348-1-song@kernel.org>
On Thu 2022-09-01 10:12:52, Song Liu wrote:
> From: Miroslav Benes <mbenes@suse.cz>
>
> Josh reported a bug:
>
> When the object to be patched is a module, and that module is
> rmmod'ed and reloaded, it fails to load with:
>
> module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 2, loc 00000000ba0302e9, val ffffffffa03e293c
> livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
> livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'
>
> The livepatch module has a relocation which references a symbol
> in the _previous_ loading of nfsd. When apply_relocate_add()
> tries to replace the old relocation with a new one, it sees that
> the previous one is nonzero and it errors out.
>
> We thus decided to reverse the relocation patching (clear all relocation
> targets on x86_64). The solution is not
> universal and is too much arch-specific, but it may prove to be simpler
> in the end.
>
> arch/powerpc/kernel/module_32.c | 10 ++++
> arch/powerpc/kernel/module_64.c | 49 +++++++++++++++
> arch/s390/kernel/module.c | 8 +++
> arch/x86/kernel/module.c | 102 +++++++++++++++++++++++---------
> include/linux/moduleloader.h | 7 +++
> kernel/livepatch/core.c | 41 ++++++++++++-
First, thanks a lot for working on this.
I can't check or test the powerpc and s390 code easily.
I am going to comment only x86 and generic code. It looks good
but it needs some changes to improve maintainability.
> 6 files changed, 189 insertions(+), 28 deletions(-)
>
> diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
> index ea6536171778..e3c312770453 100644
> --- a/arch/powerpc/kernel/module_32.c
> +++ b/arch/powerpc/kernel/module_32.c
> @@ -285,6 +285,16 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
> return 0;
> }
>
> +#ifdef CONFIG_LIVEPATCH
> +void clear_relocate_add(Elf32_Shdr *sechdrs,
> + const char *strtab,
> + unsigned int symindex,
> + unsigned int relsec,
> + struct module *me)
> +{
> +}
> +#endif
> +
> #ifdef CONFIG_DYNAMIC_FTRACE
> notrace int module_trampoline_target(struct module *mod, unsigned long addr,
> unsigned long *target)
> diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
> index 7e45dc98df8a..514951f97391 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -739,6 +739,55 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
> return 0;
> }
>
> +#ifdef CONFIG_LIVEPATCH
> +void clear_relocate_add(Elf64_Shdr *sechdrs,
> + const char *strtab,
> + unsigned int symindex,
> + unsigned int relsec,
> + struct module *me)
> +{
> + unsigned int i;
> + Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
> + Elf64_Sym *sym;
> + unsigned long *location;
> + const char *symname;
> + u32 *instruction;
> +
> + pr_debug("Clearing ADD relocate section %u to %u\n", relsec,
> + sechdrs[relsec].sh_info);
> +
> + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
> + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
> + + rela[i].r_offset;
> + sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
> + + ELF64_R_SYM(rela[i].r_info);
> + symname = me->core_kallsyms.strtab
> + + sym->st_name;
> +
> + if (ELF64_R_TYPE(rela[i].r_info) != R_PPC_REL24)
> + continue;
> + /*
> + * reverse the operations in apply_relocate_add() for case
> + * R_PPC_REL24.
> + */
> + if (sym->st_shndx != SHN_UNDEF &&
> + sym->st_shndx != SHN_LIVEPATCH)
> + continue;
> +
> + instruction = (u32 *)location;
> + if (is_mprofile_ftrace_call(symname))
> + continue;
> +
> + if (!instr_is_relative_link_branch(ppc_inst(*instruction)))
> + continue;
> +
> + instruction += 1;
> + patch_instruction(instruction, ppc_inst(PPC_RAW_NOP()));
> + }
> +
> +}
This looks like a lot of duplicated code. Isn't it?
> +#endif
> +
> #ifdef CONFIG_DYNAMIC_FTRACE
> int module_trampoline_target(struct module *mod, unsigned long addr,
> unsigned long *target)
> --- a/arch/x86/kernel/module.c
> +++ b/arch/x86/kernel/module.c
> @@ -128,18 +128,20 @@ int apply_relocate(Elf32_Shdr *sechdrs,
> return 0;
> }
> #else /*X86_64*/
> -static int __apply_relocate_add(Elf64_Shdr *sechdrs,
> +static int __apply_clear_relocate_add(Elf64_Shdr *sechdrs,
Nit: Honestly, the combination of 4 verbs: "apply", "clear, "relocate", and "add"
is really crazy. It is far from obvious what the function does.
The name was not ideal even before. Let's not make it worse and
use on 3 verbs again.
What about __update_relocate_add or __write_relocate_add()?
Note that the "__" prefix is still needed, see below.
> const char *strtab,
> unsigned int symindex,
> unsigned int relsec,
> struct module *me,
> - void *(*write)(void *dest, const void *src, size_t len))
> + void *(*write)(void *dest, const void *src, size_t len),
> + bool clear)
> {
> unsigned int i;
> Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
> Elf64_Sym *sym;
> void *loc;
> u64 val;
> + u64 zero = 0ULL;
>
> DEBUGP("Applying relocate section %u to %u\n",
> relsec, sechdrs[relsec].sh_info);
> @@ -163,40 +165,60 @@ static int __apply_relocate_add(Elf64_Shdr *sechdrs,
> case R_X86_64_NONE:
> break;
> case R_X86_64_64:
> - if (*(u64 *)loc != 0)
> - goto invalid_relocation;
> - write(loc, &val, 8);
> + if (!clear) {
Nit: I would prefer to use positive check when both if/else branches
are used. I would call the parameter "apply".
> + if (*(u64 *)loc != 0)
> + goto invalid_relocation;
> + write(loc, &val, 8);
> + } else {
> + write(loc, &zero, 8);
> + }
> break;
> case R_X86_64_32:
> - if (*(u32 *)loc != 0)
> - goto invalid_relocation;
> - write(loc, &val, 4);
> - if (val != *(u32 *)loc)
> - goto overflow;
> + if (!clear) {
> + if (*(u32 *)loc != 0)
> + goto invalid_relocation;
> + write(loc, &val, 4);
> + if (val != *(u32 *)loc)
> + goto overflow;
> + } else {
> + write(loc, &zero, 4);
> + }
> break;
> case R_X86_64_32S:
> - if (*(s32 *)loc != 0)
> - goto invalid_relocation;
> - write(loc, &val, 4);
> - if ((s64)val != *(s32 *)loc)
> - goto overflow;
> + if (!clear) {
> + if (*(s32 *)loc != 0)
> + goto invalid_relocation;
> + write(loc, &val, 4);
> + if ((s64)val != *(s32 *)loc)
> + goto overflow;
> + } else {
> + write(loc, &zero, 4);
> + }
> break;
> case R_X86_64_PC32:
> case R_X86_64_PLT32:
> - if (*(u32 *)loc != 0)
> - goto invalid_relocation;
> - val -= (u64)loc;
> - write(loc, &val, 4);
> + if (!clear) {
> + if (*(u32 *)loc != 0)
> + goto invalid_relocation;
> + val -= (u64)loc;
> + write(loc, &val, 4);
> #if 0
> - if ((s64)val != *(s32 *)loc)
> - goto overflow;
> + if ((s64)val != *(s32 *)loc)
> + goto overflow;
> #endif
> + } else {
> + write(loc, &zero, 4);
> + }
> break;
> case R_X86_64_PC64:
> - if (*(u64 *)loc != 0)
> - goto invalid_relocation;
> - val -= (u64)loc;
> - write(loc, &val, 8);
> + if (!clear) {
> + if (*(u64 *)loc != 0)
> + goto invalid_relocation;
> + val -= (u64)loc;
> + write(loc, &val, 8);
> + } else {
> + write(loc, &zero, 8);
> + }
> break;
> default:
> pr_err("%s: Unknown rela relocation: %llu\n",
> @@ -245,6 +267,32 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
> return ret;
> }
>
> +#ifdef CONFIG_LIVEPATCH
> +
> +void clear_relocate_add(Elf64_Shdr *sechdrs,
> + const char *strtab,
> + unsigned int symindex,
> + unsigned int relsec,
> + struct module *me)
> +{
> + bool early = me->state == MODULE_STATE_UNFORMED;
> + void *(*write)(void *, const void *, size_t) = memcpy;
> +
> + if (!early) {
> + write = text_poke;
> + mutex_lock(&text_mutex);
> + }
> +
> + __apply_clear_relocate_add(sechdrs, strtab, symindex, relsec, me,
> + write, true /* clear */);
> +
> + if (!early) {
> + text_poke_sync();
> + mutex_unlock(&text_mutex);
> + }
> +}
This duplicates a lot of code. Please, rename apply_relocate_add() the
same way as __apply_clear_relocate_add() and add the "apply" parameter.
Then add the wrappers for this:
int write_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me,
bool apply)
{
int ret;
bool early = me->state == MODULE_STATE_UNFORMED;
void *(*write)(void *, const void *, size_t) = memcpy;
if (!early) {
write = text_poke;
mutex_lock(&text_mutex);
}
ret = __write_relocate_add(sechdrs, strtab, symindex, relsec, me,
write, apply);
if (!early) {
text_poke_sync();
mutex_unlock(&text_mutex);
}
return ret;
}
int apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
return write_relocate_add(sechdrs, strtab, symindex, relsec, me, true);
}
#ifdef CONFIG_LIVEPATCH
void apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
write_relocate_add(sechdrs, strtab, symindex, relsec, me, false);
}
#endif
> +#endif
> +
> #endif
>
> int module_finalize(const Elf_Ehdr *hdr,
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -316,6 +316,45 @@ int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
> return apply_relocate_add(sechdrs, strtab, symndx, secndx, pmod);
> }
>
> +static void klp_clear_object_relocations(struct module *pmod,
> + struct klp_object *obj)
> +{
> + int i, cnt;
> + const char *objname, *secname;
> + char sec_objname[MODULE_NAME_LEN];
> + Elf_Shdr *sec;
> +
> + objname = klp_is_module(obj) ? obj->name : "vmlinux";
> +
> + /* For each klp relocation section */
> + for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) {
> + sec = pmod->klp_info->sechdrs + i;
> + secname = pmod->klp_info->secstrings + sec->sh_name;
> + if (!(sec->sh_flags & SHF_RELA_LIVEPATCH))
> + continue;
> +
> + /*
> + * Format: .klp.rela.sec_objname.section_name
> + * See comment in klp_resolve_symbols() for an explanation
> + * of the selected field width value.
> + */
> + secname = pmod->klp_info->secstrings + sec->sh_name;
> + cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname);
> + if (cnt != 1) {
> + pr_err("section %s has an incorrectly formatted name\n",
> + secname);
> + continue;
> + }
> +
> + if (strcmp(objname, sec_objname))
> + continue;
> +
> + clear_relocate_add(pmod->klp_info->sechdrs,
> + pmod->core_kallsyms.strtab,
> + pmod->klp_info->symndx, i, pmod);
> + }
> +}
Huh, this duplicates a lot of tricky code.
It is even worse because this squashed code from two functions
klp_apply_section_relocs() and klp_apply_object_relocs()
into a single function. As a result, the code duplication is not
even obvious.
Also the suffix "_reloacations() does not match the suffix of
the related funciton:
+ klp_apply_object_relocs() (existing)
+ klp_clear_object_relocations() (new)
This all would complicate maintenance of the code.
Please, implement a common:
int klp_write_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
const char *shstrtab, const char *strtab,
unsigned int symndx, unsigned int secndx,
const char *objname, bool apply);
and
int klp_write_object_relocs(struct klp_patch *patch,
struct klp_object *obj,
bool apply);
and add the respective wrappers:
int klp_apply_section_relocs(); /* also needed in module/main.c */
int klp_apply_object_relocs();
void klp_clear_object_relocs();
Best Regards,
Petr
next prev parent reply other threads:[~2022-11-18 16:24 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-01 17:12 [PATCH v6] livepatch: Clear relocation targets on a module removal Song Liu
2022-09-01 17:12 ` Song Liu
2022-11-17 22:06 ` Song Liu
2022-11-17 22:06 ` Song Liu
2022-11-18 16:24 ` Petr Mladek [this message]
2022-11-18 16:24 ` Petr Mladek
2022-11-18 17:14 ` Song Liu
2022-11-18 17:14 ` Song Liu
2022-11-21 15:32 ` Joe Lawrence
2022-11-21 15:32 ` Joe Lawrence
2022-11-21 16:32 ` Song Liu
2022-11-21 16:32 ` Song Liu
2022-11-29 1:57 ` Song Liu
2022-11-29 1:57 ` Song Liu
2022-12-09 11:41 ` powerpc-part: was: " Petr Mladek
2022-12-09 11:41 ` Petr Mladek
2022-12-09 19:59 ` Song Liu
2022-12-09 19:59 ` Song Liu
2022-12-12 17:11 ` Petr Mladek
2022-12-12 17:11 ` Petr Mladek
2022-12-12 22:22 ` Song Liu
2022-12-12 22:22 ` Song Liu
2022-12-13 8:13 ` Song Liu
2022-12-13 8:13 ` Song Liu
2022-12-13 13:29 ` Petr Mladek
2022-12-13 13:29 ` Petr Mladek
2022-12-13 22:19 ` Joe Lawrence
2022-12-13 22:19 ` Joe Lawrence
2022-12-13 19:31 ` Song Liu
2022-12-13 19:31 ` Song Liu
2022-12-09 12:36 ` x86 part: " Petr Mladek
2022-12-09 12:36 ` Petr Mladek
2022-12-09 12:49 ` Miroslav Benes
2022-12-09 12:49 ` Miroslav Benes
2022-12-09 13:54 ` Petr Mladek
2022-12-09 13:54 ` Petr Mladek
2022-12-09 14:20 ` Petr Mladek
2022-12-09 14:20 ` Petr Mladek
2022-12-09 18:21 ` Song Liu
2022-12-09 18:21 ` Song Liu
2022-12-09 12:55 ` Miroslav Benes
2022-12-09 12:55 ` Miroslav Benes
2022-12-09 18:30 ` Song Liu
2022-12-09 18:30 ` Song Liu
2022-12-09 18:51 ` Christophe Leroy
2022-12-09 18:51 ` Christophe Leroy
2022-12-09 19:24 ` Song Liu
2022-12-09 19:24 ` Song Liu
2022-12-12 8:16 ` Miroslav Benes
2022-12-12 8:16 ` Miroslav Benes
2022-12-13 8:28 ` Song Liu
2022-12-13 8:28 ` Song Liu
2022-12-13 14:37 ` Petr Mladek
2022-12-13 14:37 ` Petr Mladek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y3expGRt4cPoZgHL@alley \
--to=pmladek@suse.com \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=jpoimboe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=song@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.