linux
Attempt to set a breakpoint resulted in kernel panic
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;