
Kprobes allows you to break into any kernel routine by modifying the OPCODE of an instruction (Kernel's text pages). In PPC32, kernel text pages are write-protected even if KPROBES is enabled. Thus, when arch_arm_kprobes() attempts to set a breakpoint, i.e. to write a kernel text address, this causes a segmentation fault.
Bug fixed by commit 221ac329e93
Type | WriteOnReadOnly |
Config | "!PPC64 && KPROBES && !KGDB && !XMON && !BDI_SWITCH" (5th degree) |
Fix-in | mapping |
Location | arch/powerpc/kernel/ |
#include <unistd.h> #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) char *buffer; #if !defined(CONFIG_KGDB) && !defined(CONFIG_XMON) && !defined(CONFIG_BDI_SWITCH) void allocate_buffer() { int pagesize; pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize == -1) handle_error("sysconf"); buffer = memalign(pagesize, 4*pagesize); if (buffer == NULL) handle_error("memalign"); if (mprotect(buffer, 4*pagesize, PROT_READ) == -1) handle_error("mprotect"); } #else #define allocate_buffer() ({ buffer = malloc(4092); }) #endif int main(int argc, char** argv) { allocate_buffer(); #ifdef CONFIG_KPROBES *buffer = 'a'; // ERROR #endif return 0; }
diff --git a/simple/221ac32.c b/simple/221ac32.c --- a/simple/221ac32.c +++ b/simple/221ac32.c @@ -10,7 +10,7 @@ char *buffer; -#if !defined(CONFIG_KGDB) && !defined(CONFIG_XMON) && !defined(CONFIG_BDI_SWITCH) +#if !defined(CONFIG_KGDB) && !defined(CONFIG_XMON) && !defined(CONFIG_BDI_SWITCH) && !defined(CONFIG_KPROBES) void allocate_buffer() { int pagesize;
#include <unistd.h> #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <errno.h> #include <sys/mman.h> int main(int argc, char** argv) { char *buffer; // allocate_buffer(); #if !defined(CONFIG_KGDB) && !defined(CONFIG_XMON) && !defined(CONFIG_BDI_SWITCH) int pagesize; pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize == -1) do { perror("sysconf"); exit(EXIT_FAILURE); } while (0); buffer = memalign(pagesize, 4*pagesize); if (buffer == NULL) do { perror("memalign"); exit(EXIT_FAILURE); } while (0); if (mprotect(buffer, 4*pagesize, PROT_READ) == -1) do { perror("mprotect"); exit(EXIT_FAILURE); } while (0); #else buffer = malloc(4092); #endif #ifdef CONFIG_KPROBES *buffer = 'a'; // ERROR #endif return 0; }
. arch/powerpc/kernel/kprobes.c:75:arch_arm_kprobe() . 77: *p->addr = BREAKPOINT_INSTRUCTION;