Re: [PATCH v9 3/8] powerpc/kprobes: Mark newly allocated probes as RO
From: Jordan Niethe <hidden>
Date: 2021-03-17 00:53:19
On Tue, Mar 16, 2021 at 5:44 PM Christophe Leroy [off-list ref] wrote:
Le 16/03/2021 à 04:17, Jordan Niethe a écrit :quoted
From: Russell Currey <redacted> With CONFIG_STRICT_KERNEL_RWX=y and CONFIG_KPROBES=y, there will be one W+X page at boot by default. This can be tested with CONFIG_PPC_PTDUMP=y and CONFIG_PPC_DEBUG_WX=y set, and checking the kernel log during boot.This text is confusing. I don't understand what is the status before the patch, and what is the status after. "there will be one ...", does it mean after the patch ?quoted
Add an arch specific insn page allocator which returns RO pages if STRICT_KERNEL_RWX is enabled. This page is only written to with patch_instruction() which is able to write RO pages."an" or "the" arch specific insn page allocator ?quoted
Reviewed-by: Daniel Axtens <redacted> Signed-off-by: Russell Currey <redacted> Signed-off-by: Christophe Leroy <redacted> [jpn: Reword commit message, switch from vmalloc_exec(), add free_insn_page()] Signed-off-by: Jordan Niethe <redacted> --- v9: - vmalloc_exec() no longer exists - Set the page to RW before freeing it --- arch/powerpc/kernel/kprobes.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 01ab2163659e..bb7e4d321988 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c@@ -25,6 +25,8 @@ #include <asm/sections.h> #include <asm/inst.h> #include <linux/uaccess.h> +#include <linux/set_memory.h> +#include <linux/vmalloc.h> DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);@@ -103,6 +105,26 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) return addr; } +void *alloc_insn_page(void) +{ + void *page = vmalloc(PAGE_SIZE);Can't do that on book3s/32, see https://github.com/linuxppc/linux/commit/6ca05532 and https://github.com/linuxppc/linux/commit/7fbc22ce Should do: return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, GFP_KERNEL, PAGE_KERNEL_ROX, VM_FLUSH_RESET_PERMS, NUMA_NO_NODE, __builtin_return_address(0)); To keep it simple, you'll probably need to define MODULES_VADDR and MODULES_END as resp VMALLOC_START and VMALLOC_END when they are not defined, maybe in asm/pgtable.h
Thank you, I had overlooked that. I will do it like that in the next revision.
quoted
+ + if (!page) + return NULL; + + set_memory_ro((unsigned long)page, 1); + set_memory_x((unsigned long)page, 1); + + return page; +} + +void free_insn_page(void *page) +{ + set_memory_nx((unsigned long)page, 1); + set_memory_rw((unsigned long)page, 1); + vfree(page); +} + int arch_prepare_kprobe(struct kprobe *p) { int ret = 0;