Skip to contentSkip to conversation

livepatch: Clear relocation targets on a module removal

PATCH Superseded Song Liu 4 participants 12 messages Jul 21, 2022 – Aug 2, 2022

Subsystems (5)
x86 PowerPC s390 Module support +1 more subsystems

v3 of 9 Superseded Latest is v9 →

lore
Share & tools
lore

Song Liu

author maintainer
#0 lore raw

PATCH v3 1/1 livepatch: Clear relocation targets on a module removal

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

He also proposed three different solutions. We could remove the error check in apply_relocate_add() introduced by commit eda9cec4c9a1 ("x86/module: Detect and skip invalid relocations"). However the check is useful for detecting corrupted modules.

We could also deny the patched modules to be removed. If it proved to be a major drawback for users, we could still implement a different approach. The solution would also complicate the existing code a lot.

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.

---

Changes from v2:
1. Rewrite x86 changes to match current code style.
2. Remove powerpc changes as there is no test coverage in v3.
3. Only keep 1/3 of v2.

v2: https://lore.kernel.org/all/[email protected]/T/#u

---
 arch/powerpc/kernel/module_64.c | 10 ++++
 arch/s390/kernel/module.c       |  8 ++++
 arch/x86/kernel/module.c        | 85 +++++++++++++++++++++++++++++++++
 include/linux/moduleloader.h    |  7 +++
 kernel/livepatch/core.c         | 41 +++++++++++++++-
 5 files changed, 150 insertions(+), 1 deletion(-)
arch/powerpc/kernel/module_64.c +10 -0
index 7e45dc98df8a..9125f0aff5d4 100644
@@ -739,6 +739,16 @@ 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)
+{
+}
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 int module_trampoline_target(struct module *mod, unsigned long addr,
 			     unsigned long *target)
arch/s390/kernel/module.c +8 -0
index 26125a9c436d..abbf45715354 100644
@@ -500,6 +500,14 @@ static int module_alloc_ftrace_hotpatch_trampolines(struct module *me,
 }
 #endif /* CONFIG_FUNCTION_TRACER */
 
+#ifdef CONFIG_LIVEPATCH
+void clear_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
+			unsigned int symindex, unsigned int relsec,
+			struct module *me)
+{
+}
+#endif
+
 int module_finalize(const Elf_Ehdr *hdr,
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
arch/x86/kernel/module.c +85 -0

91 lines not on this page · raw message

include/linux/moduleloader.h +7 -0
index 9e09d11ffe5b..d22b36b84b4b 100644
@@ -72,6 +72,13 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
 		       unsigned int symindex,
 		       unsigned int relsec,
 		       struct module *mod);
+#ifdef CONFIG_LIVEPATCH
+void clear_relocate_add(Elf64_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me);
+#endif
 #else
 static inline int apply_relocate_add(Elf_Shdr *sechdrs,
 				     const char *strtab,
kernel/livepatch/core.c +40 -1

53 lines not on this page · raw message

Signature · 1 line
2.30.2
author maintainer
#1 lore raw

Hi folks,

Could you please share your comments on this one?

Thanks,
Song

Quoted 50 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

He also proposed three different solutions. We could remove the error check in apply_relocate_add() introduced by commit eda9cec4c9a1 ("x86/module: Detect and skip invalid relocations"). However the check is useful for detecting corrupted modules.

We could also deny the patched modules to be removed. If it proved to be a major drawback for users, we could still implement a different approach. The solution would also complicate the existing code a lot.

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.

---

Changes from v2:
1. Rewrite x86 changes to match current code style.
2. Remove powerpc changes as there is no test coverage in v3.
3. Only keep 1/3 of v2.

v2: https://lore.kernel.org/all/[email protected]/T/#u
---

[...]

maintainer
#2 lore raw
In reply to Song Liu
Quoted 40 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

He also proposed three different solutions. We could remove the error check in apply_relocate_add() introduced by commit eda9cec4c9a1 ("x86/module: Detect and skip invalid relocations"). However the check is useful for detecting corrupted modules.

We could also deny the patched modules to be removed. If it proved to be a major drawback for users, we could still implement a different approach. The solution would also complicate the existing code a lot.

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.

Quoted 6 lines

---

Changes from v2:
1. Rewrite x86 changes to match current code style.
2. Remove powerpc changes as there is no test coverage in v3.
3. Only keep 1/3 of v2.

1) All the copy/paste is ugly and IMO guaranteed to eventually introduce bugs when somebody forgets to update the copy. Wouldn't it be more robust to reuse the existing apply_relocate_add() code by making it more generic somehow, like with a new 'clear' bool arg which sets 'val' to zero?

2) We can't only fix x86, powerpc also needs a fix.

3) A selftest would be a good idea.

Signature · 1 line
Josh
author maintainer
#3 lore raw
Quoted 49 lines · Josh Poimboeuf
Quoted 40 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

He also proposed three different solutions. We could remove the error check in apply_relocate_add() introduced by commit eda9cec4c9a1 ("x86/module: Detect and skip invalid relocations"). However the check is useful for detecting corrupted modules.

We could also deny the patched modules to be removed. If it proved to be a major drawback for users, we could still implement a different approach. The solution would also complicate the existing code a lot.

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.

Quoted 6 lines

---

Changes from v2:
1. Rewrite x86 changes to match current code style.
2. Remove powerpc changes as there is no test coverage in v3.
3. Only keep 1/3 of v2.

Quoted 5 lines

1) All the copy/paste is ugly and IMO guaranteed to eventually introduce bugs when somebody forgets to update the copy. Wouldn't it be more robust to reuse the existing apply_relocate_add() code by making it more generic somehow, like with a new 'clear' bool arg which sets 'val' to zero?

Agreed. I can give it a try.

Quoted 2 lines

2) We can't only fix x86, powerpc also needs a fix.

I have very little experience with powerpc. Would someone be willing to help with powerpc part of this?

Quoted 1 line

3) A selftest would be a good idea.

I will try this.

Thanks,
Song

author maintainer
#4 lore raw
Quoted 51 lines · Song Liu
Quoted 49 lines · Josh Poimboeuf
Quoted 46 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

He also proposed three different solutions. We could remove the error check in apply_relocate_add() introduced by commit eda9cec4c9a1 ("x86/module: Detect and skip invalid relocations"). However the check is useful for detecting corrupted modules.

We could also deny the patched modules to be removed. If it proved to be a major drawback for users, we could still implement a different approach. The solution would also complicate the existing code a lot.

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.

---

Changes from v2:
1. Rewrite x86 changes to match current code style.
2. Remove powerpc changes as there is no test coverage in v3.
3. Only keep 1/3 of v2.

Quoted 7 lines
Quoted 5 lines

1) All the copy/paste is ugly and IMO guaranteed to eventually introduce bugs when somebody forgets to update the copy. Wouldn't it be more robust to reuse the existing apply_relocate_add() code by making it more generic somehow, like with a new 'clear' bool arg which sets 'val' to zero?

Agreed. I can give it a try.

I finished this part, though it is not really clean (added if else for each "case:").

Quoted 6 lines
Quoted 3 lines

2) We can't only fix x86, powerpc also needs a fix.

I have very little experience with powerpc. Would someone be willing to help with powerpc part of this?

I guess folks are all busy. Any suggestions on how to test powerpc changes?

Quoted 3 lines
Quoted 2 lines

3) A selftest would be a good idea.

I found it is pretty tricky to run the selftests inside a qemu VM. How about we test it with modules in samples/livepatch? Specifically, we can add a script try to reload livepatch-shadow-mod.ko.

Thanks,
Song

author maintainer
#5 lore raw
Quoted 74 lines · Song Liu
Quoted 51 lines · Song Liu
Quoted 49 lines · Josh Poimboeuf
Quoted 46 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

He also proposed three different solutions. We could remove the error check in apply_relocate_add() introduced by commit eda9cec4c9a1 ("x86/module: Detect and skip invalid relocations"). However the check is useful for detecting corrupted modules.

We could also deny the patched modules to be removed. If it proved to be a major drawback for users, we could still implement a different approach. The solution would also complicate the existing code a lot.

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.

---

Changes from v2:
1. Rewrite x86 changes to match current code style.
2. Remove powerpc changes as there is no test coverage in v3.
3. Only keep 1/3 of v2.

Quoted 7 lines
Quoted 5 lines

1) All the copy/paste is ugly and IMO guaranteed to eventually introduce bugs when somebody forgets to update the copy. Wouldn't it be more robust to reuse the existing apply_relocate_add() code by making it more generic somehow, like with a new 'clear' bool arg which sets 'val' to zero?

Agreed. I can give it a try.

I finished this part, though it is not really clean (added if else for each "case:").

Quoted 6 lines
Quoted 3 lines

2) We can't only fix x86, powerpc also needs a fix.

I have very little experience with powerpc. Would someone be willing to help with powerpc part of this?

I guess folks are all busy. Any suggestions on how to test powerpc changes?

Quoted 1 line
Quoted 6 lines
Quoted 2 lines
Quoted 1 line

3) A selftest would be a good idea.

I found it is pretty tricky to run the selftests inside a qemu VM. How about we test it with modules in samples/livepatch? Specifically, we can add a script try to reload livepatch-shadow-mod.ko.

Actually, livepatch-shadow-mod.ko doesn't have the reload problem before the fix. Is this expected?

Thanks,
Song

maintainer
#6 lore raw
Quoted 32 lines · Song Liu
Quoted 31 lines · Song Liu
Quoted 28 lines · Song Liu
Quoted 25 lines · Josh Poimboeuf
Quoted 16 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

Quoted 6 lines

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

3) A selftest would be a good idea.

Quoted 6 lines
Quoted 3 lines

I found it is pretty tricky to run the selftests inside a qemu VM. How about we test it with modules in samples/livepatch? Specifically, we can add a script try to reload livepatch-shadow-mod.ko.

Actually, livepatch-shadow-mod.ko doesn't have the reload problem before the fix. Is this expected?

Good question. I am afraid that there is no easy way to prepare the selftest at the moment.

There are two situations when a symbol from the livepatched module is relocated:

1. The livepatch might access a symbol exported by the module via EXPORT_SYMBOL(). In this case, it is "normal" external symbol and it gets relocated by the module loader.

But EXPORT_SYMBOL() will create an explicit dependency between the livepatch and livepatched module. As a result, the livepatch module could be loaded only when the livepatched module is loaded. And the livepatched module could not be removed when the livepatch module is loaded.

In this case, the problem will not exist. Well, the developers of the livepatch module will probably want to avoid this dependency.

2. The livepatch module might access a non-exported symbol from another module using the special elf section for klp relocation, see section, see Documentation/livepatch/module-elf-format.rst

These symbols are relocated in klp_apply_section_relocs().

The problem is that upstream does not have a support to create this elf section. There is a patchset for this, see
https://lore.kernel.org/all/[email protected]/
It requires some more review.

Resume: I think that we could not prepare the selftest without
upstreaming klp-convert tool.

Best Regards,
Petr

author maintainer
#7 lore raw
Quoted 69 lines · Petr Mladek
Quoted 32 lines · Song Liu
Quoted 31 lines · Song Liu
Quoted 28 lines · Song Liu
Quoted 25 lines · Josh Poimboeuf
Quoted 16 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

Quoted 6 lines

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

3) A selftest would be a good idea.

Quoted 6 lines
Quoted 3 lines

I found it is pretty tricky to run the selftests inside a qemu VM. How about we test it with modules in samples/livepatch? Specifically, we can add a script try to reload livepatch-shadow-mod.ko.

Actually, livepatch-shadow-mod.ko doesn't have the reload problem before the fix. Is this expected?

Good question. I am afraid that there is no easy way to prepare the selftest at the moment.

There are two situations when a symbol from the livepatched module is relocated:

1. The livepatch might access a symbol exported by the module via EXPORT_SYMBOL(). In this case, it is "normal" external symbol and it gets relocated by the module loader.

But EXPORT_SYMBOL() will create an explicit dependency between the livepatch and livepatched module. As a result, the livepatch module could be loaded only when the livepatched module is loaded. And the livepatched module could not be removed when the livepatch module is loaded.

In this case, the problem will not exist. Well, the developers of the livepatch module will probably want to avoid this dependency.

2. The livepatch module might access a non-exported symbol from another module using the special elf section for klp relocation, see section, see Documentation/livepatch/module-elf-format.rst

These symbols are relocated in klp_apply_section_relocs().

Quoted 8 lines

The problem is that upstream does not have a support to create this elf section. There is a patchset for this, see
https://lore.kernel.org/all/[email protected]/
It requires some more review.

Resume: I think that we could not prepare the selftest without
upstreaming klp-convert tool.

Thanks for the explanation! I suspected the same issue, but couldn't connect all the logic.

I guess the selftests can wait until the klp-convert tool.

Thanks,
Song

maintainer
#8 lore raw
Quoted 76 lines · Song Liu
Quoted 75 lines · Petr Mladek
Quoted 32 lines · Song Liu
Quoted 31 lines · Song Liu
Quoted 28 lines · Song Liu
Quoted 25 lines · Josh Poimboeuf
Quoted 16 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

Quoted 6 lines

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

3) A selftest would be a good idea.

Quoted 6 lines
Quoted 3 lines

I found it is pretty tricky to run the selftests inside a qemu VM. How about we test it with modules in samples/livepatch? Specifically, we can add a script try to reload livepatch-shadow-mod.ko.

Actually, livepatch-shadow-mod.ko doesn't have the reload problem before the fix. Is this expected?

Good question. I am afraid that there is no easy way to prepare the selftest at the moment.

There are two situations when a symbol from the livepatched module is relocated:

1. The livepatch might access a symbol exported by the module via EXPORT_SYMBOL(). In this case, it is "normal" external symbol and it gets relocated by the module loader.

But EXPORT_SYMBOL() will create an explicit dependency between the livepatch and livepatched module. As a result, the livepatch module could be loaded only when the livepatched module is loaded. And the livepatched module could not be removed when the livepatch module is loaded.

In this case, the problem will not exist. Well, the developers of the livepatch module will probably want to avoid this dependency.

2. The livepatch module might access a non-exported symbol from another module using the special elf section for klp relocation, see section, see Documentation/livepatch/module-elf-format.rst

These symbols are relocated in klp_apply_section_relocs().

The problem is that upstream does not have a support to create this elf section. There is a patchset for this, see
https://lore.kernel.org/all/[email protected]/
It requires some more review.

Quoted 8 lines
Quoted 2 lines

Resume: I think that we could not prepare the selftest without
upstreaming klp-convert tool.

Thanks for the explanation! I suspected the same issue, but couldn't connect all the logic.

I guess the selftests can wait until the klp-convert tool.

Hi Song,

Petr is correct about selftests and these relocations. Let me know if rebasing the klp-convert patchset would be helpful in your testing. Otherwise kpatch-build is the only (easy?) way to create klp-relocations as far as I know. (For limited arches anyway.)

Thanks,

Signature · 1 line
Joe
author maintainer
#9 lore raw

Hi Joe,

Quoted 87 lines · Joe Lawrence
Quoted 76 lines · Song Liu
Quoted 75 lines · Petr Mladek
Quoted 32 lines · Song Liu
Quoted 31 lines · Song Liu
Quoted 28 lines · Song Liu
Quoted 25 lines · Josh Poimboeuf
Quoted 16 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

Quoted 6 lines

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

3) A selftest would be a good idea.

Quoted 6 lines
Quoted 3 lines

I found it is pretty tricky to run the selftests inside a qemu VM. How about we test it with modules in samples/livepatch? Specifically, we can add a script try to reload livepatch-shadow-mod.ko.

Actually, livepatch-shadow-mod.ko doesn't have the reload problem before the fix. Is this expected?

Good question. I am afraid that there is no easy way to prepare the selftest at the moment.

There are two situations when a symbol from the livepatched module is relocated:

1. The livepatch might access a symbol exported by the module via EXPORT_SYMBOL(). In this case, it is "normal" external symbol and it gets relocated by the module loader.

But EXPORT_SYMBOL() will create an explicit dependency between the livepatch and livepatched module. As a result, the livepatch module could be loaded only when the livepatched module is loaded. And the livepatched module could not be removed when the livepatch module is loaded.

In this case, the problem will not exist. Well, the developers of the livepatch module will probably want to avoid this dependency.

2. The livepatch module might access a non-exported symbol from another module using the special elf section for klp relocation, see section, see Documentation/livepatch/module-elf-format.rst

These symbols are relocated in klp_apply_section_relocs().

The problem is that upstream does not have a support to create this elf section. There is a patchset for this, see
https://lore.kernel.org/all/[email protected]/
It requires some more review.

Quoted 8 lines
Quoted 2 lines

Resume: I think that we could not prepare the selftest without
upstreaming klp-convert tool.

Thanks for the explanation! I suspected the same issue, but couldn't connect all the logic.

I guess the selftests can wait until the klp-convert tool.

Quoted 6 lines

Hi Song,

Petr is correct about selftests and these relocations. Let me know if rebasing the klp-convert patchset would be helpful in your testing. Otherwise kpatch-build is the only (easy?) way to create klp-relocations as far as I know. (For limited arches anyway.)

I was able to test the patch on x86_64 with kpatch-build. I will look into klp-convert later (after I fix kpatch-build for some OOT modules..)

I the meanwhile, I guess this patch doesn't need to wait for klp-convert and the selftest?

Thanks,
Song

maintainer
#10 lore raw
In reply to Song Liu
Quoted 27 lines · Song Liu
Quoted 26 lines · Song Liu
Quoted 24 lines · Josh Poimboeuf
Quoted 22 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

2) We can't only fix x86, powerpc also needs a fix.

I have very little experience with powerpc. Would someone be willing to help with powerpc part of this?

I guess folks are all busy. Any suggestions on how to test powerpc changes?

You might also send the patch and just mention that you were not able to test it on powerpc. There are people with access to powerpc that might check it.

Another question is how to actually test it. I wonder how you do it for x86.

Finally, also s390 supports livepatching. I guess that the problem is there as well. Is is straightforward to write the revert code, please?

Best Regards,
Petr

author maintainer
#11 lore raw
Quoted 31 lines · Petr Mladek
Quoted 29 lines · Song Liu
Quoted 28 lines · Song Liu
Quoted 25 lines · Josh Poimboeuf
Quoted 16 lines · Song Liu

From: Miroslav Benes <[email protected]>

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.

Quoted 6 lines

On ppc64le, we have a similar issue:

module_64: livepatch_nfsd: Expected nop after call, got e8410018 at e_show+0x60/0x548 [livepatch_nfsd]
livepatch: failed to initialize patch 'livepatch_nfsd' for module 'nfsd' (-8)
livepatch: patch 'livepatch_nfsd' failed for module 'nfsd', refusing to load module 'nfsd'

2) We can't only fix x86, powerpc also needs a fix.

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

I have very little experience with powerpc. Would someone be willing to help with powerpc part of this?

I guess folks are all busy. Any suggestions on how to test powerpc changes?

You might also send the patch and just mention that you were not able to test it on powerpc. There are people with access to powerpc that might check it.

Let me give it a try.

Quoted 3 lines

Another question is how to actually test it. I wonder how you do it for x86.

I tested it with a patch on an in-tree module. I was using kpatch-build and testing it on 5.18 kernels. This is tricky at the moment for 5.19 because of this issue:

https://github.com/dynup/kpatch/issues/1277

Quoted 3 lines

Finally, also s390 supports livepatching. I guess that the problem is there as well. Is is straightforward to write the revert code, please?

v2 of the work doesn't have any real logic for s390. I wonder whether it is needed.

Thanks,
Song

v2: https://lore.kernel.org/all/[email protected]/T/#u