From 3d4e0c095d4fe862c4a1a5dbfc94c8a09a187fd3 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Thu, 5 Jul 2018 09:49:59 +0100 Subject: [PATCH] kprobe: update example with px Going to try and upstream this later on --- README.adoc | 28 ++++++++++++++++++-------- kernel_module/kprobe_example.c | 36 ++++++++++++---------------------- kernel_module/pci.c | 4 ++-- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/README.adoc b/README.adoc index 92927d3..65330e0 100644 --- a/README.adoc +++ b/README.adoc @@ -4405,26 +4405,38 @@ TODO: can you get function arguments? https://stackoverflow.com/questions/276087 ==== Kprobes +kprobes is an instrumentation mechanism that injects arbitrary code at a given address in a trap instruction, much like GDB. Oh, the good old kernel. :-) + .... ./build -C 'CONFIG_KPROBES=y' -./run -F 'insmod /kprobe_example.ko && sleep 4 & sleep 4 &' +.... + +Then on guest: + +.... +insmod /kprobe_example.ko +sleep 4 & sleep 4 &' +.... + +Outcome: dmesg outputs on every fork: + +.... +<_do_fork> pre_handler: p->addr = 0x00000000e1360063, ip = ffffffff810531d1, flags = 0x246 +<_do_fork> post_handler: p->addr = 0x00000000e1360063, flags = 0x246 +<_do_fork> pre_handler: p->addr = 0x00000000e1360063, ip = ffffffff810531d1, flags = 0x246 +<_do_fork> post_handler: p->addr = 0x00000000e1360063, flags = 0x246 .... Source: link:kernel_module/kprobe_example.c[] -Outcome: every fork spits out some extra printks of type: +TODO: it does not work if I try to immediately launch `sleep`, why? .... -<6>[ 2.011117] <_do_fork> pre_handler: p->addr = 0x00000000e1360063, ip = ffffffff810531d1, flags = 0x246 -<6>[ 2.011622] <_do_fork> post_handler: p->addr = 0x00000000e1360063, flags = 0x246 -<6>[ 2.021860] <_do_fork> pre_handler: p->addr = 0x00000000e1360063, ip = ffffffff810531d1, flags = 0x246 -<6>[ 2.022331] <_do_fork> post_handler: p->addr = 0x00000000e1360063, flags = 0x246 +insmod /kprobe_example.ko && sleep 4 & sleep 4 & .... Docs: https://github.com/torvalds/linux/blob/v4.16/Documentation/kprobes.txt -Injects arbitrary code at a given address in a trap instruction, much like GDB. Oh the good old kernel. :-) - I don't think your code can refer to the surrounding kernel code however: the only visible thing is the value of the registers. You can then hack it up to read the stack and read argument values, but do you really want to? diff --git a/kernel_module/kprobe_example.c b/kernel_module/kprobe_example.c index ef2405d..fe3e645 100644 --- a/kernel_module/kprobe_example.c +++ b/kernel_module/kprobe_example.c @@ -1,5 +1,3 @@ -/* Upstream: https://github.com/torvalds/linux/blob/v4.16/samples/kprobes/kprobe_example.c */ - /* * NOTE: This example is works on x86 and powerpc. * Here's a sample kernel module showing the use of kprobes to dump a @@ -29,28 +27,24 @@ static struct kprobe kp = { static int handler_pre(struct kprobe *p, struct pt_regs *regs) { #ifdef CONFIG_X86 - pr_info("<%s> pre_handler: p->addr = 0x%p, ip = %lx, flags = 0x%lx\n", + pr_info("<%s> pre_handler: p->addr = 0x%px, ip = %lx, flags = 0x%lx\n", p->symbol_name, p->addr, regs->ip, regs->flags); #endif #ifdef CONFIG_PPC - pr_info("<%s> pre_handler: p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx\n", + pr_info("<%s> pre_handler: p->addr = 0x%px, nip = 0x%lx, msr = 0x%lx\n", p->symbol_name, p->addr, regs->nip, regs->msr); #endif #ifdef CONFIG_MIPS - pr_info("<%s> pre_handler: p->addr = 0x%p, epc = 0x%lx, status = 0x%lx\n", + pr_info("<%s> pre_handler: p->addr = 0x%px, epc = 0x%lx, status = 0x%lx\n", p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status); #endif -#ifdef CONFIG_TILEGX - pr_info("<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx, ex1 = 0x%lx\n", - p->symbol_name, p->addr, regs->pc, regs->ex1); -#endif #ifdef CONFIG_ARM64 - pr_info("<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx," + pr_info("<%s> pre_handler: p->addr = 0x%px, pc = 0x%lx," " pstate = 0x%lx\n", p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate); #endif #ifdef CONFIG_S390 - pr_info("<%s> pre_handler: p->addr, 0x%p, ip = 0x%lx, flags = 0x%lx\n", + pr_info("<%s> pre_handler: p->addr, 0x%px, ip = 0x%lx, flags = 0x%lx\n", p->symbol_name, p->addr, regs->psw.addr, regs->flags); #endif @@ -63,27 +57,23 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) { #ifdef CONFIG_X86 - pr_info("<%s> post_handler: p->addr = 0x%p, flags = 0x%lx\n", + pr_info("<%s> post_handler: p->addr = 0x%px, flags = 0x%lx\n", p->symbol_name, p->addr, regs->flags); #endif #ifdef CONFIG_PPC - pr_info("<%s> post_handler: p->addr = 0x%p, msr = 0x%lx\n", + pr_info("<%s> post_handler: p->addr = 0x%px, msr = 0x%lx\n", p->symbol_name, p->addr, regs->msr); #endif #ifdef CONFIG_MIPS - pr_info("<%s> post_handler: p->addr = 0x%p, status = 0x%lx\n", + pr_info("<%s> post_handler: p->addr = 0x%px, status = 0x%lx\n", p->symbol_name, p->addr, regs->cp0_status); #endif -#ifdef CONFIG_TILEGX - pr_info("<%s> post_handler: p->addr = 0x%p, ex1 = 0x%lx\n", - p->symbol_name, p->addr, regs->ex1); -#endif #ifdef CONFIG_ARM64 - pr_info("<%s> post_handler: p->addr = 0x%p, pstate = 0x%lx\n", + pr_info("<%s> post_handler: p->addr = 0x%px, pstate = 0x%lx\n", p->symbol_name, p->addr, (long)regs->pstate); #endif #ifdef CONFIG_S390 - pr_info("<%s> pre_handler: p->addr, 0x%p, flags = 0x%lx\n", + pr_info("<%s> pre_handler: p->addr, 0x%px, flags = 0x%lx\n", p->symbol_name, p->addr, regs->flags); #endif } @@ -95,7 +85,7 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs, */ static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) { - pr_info("fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr); + pr_info("fault_handler: p->addr = 0x%px, trap #%dn", p->addr, trapnr); /* Return 0 because we don't handle the fault. */ return 0; } @@ -112,14 +102,14 @@ static int __init kprobe_init(void) pr_err("register_kprobe failed, returned %d\n", ret); return ret; } - pr_info("Planted kprobe at %p\n", kp.addr); + pr_info("Planted kprobe at %px\n", kp.addr); return 0; } static void __exit kprobe_exit(void) { unregister_kprobe(&kp); - pr_info("kprobe at %p unregistered\n", kp.addr); + pr_info("kprobe at %px unregistered\n", kp.addr); } module_init(kprobe_init) diff --git a/kernel_module/pci.c b/kernel_module/pci.c index 65cb2d9..4f799ac 100644 --- a/kernel_module/pci.c +++ b/kernel_module/pci.c @@ -207,7 +207,7 @@ static int pci_probe(struct pci_dev *dev, const struct pci_device_id *id) /* RAM -> device. */ vaddr_from = dma_alloc_coherent(&(dev->dev), 4, &dma_handle_from, GFP_ATOMIC); - dev_info(&(dev->dev), "vaddr_from = %p\n", vaddr_from); + dev_info(&(dev->dev), "vaddr_from = %px\n", vaddr_from); dev_info(&(dev->dev), "dma_handle_from = %llx\n", (unsigned long long)dma_handle_from); *((volatile u32*)vaddr_from) = 0x12345678; iowrite32((u32)dma_handle_from, mmio + IO_DMA_SRC); @@ -217,7 +217,7 @@ static int pci_probe(struct pci_dev *dev, const struct pci_device_id *id) /* device -> RAM. */ vaddr_to = dma_alloc_coherent(&(dev->dev), 4, &dma_handle_to, GFP_ATOMIC); - dev_info(&(dev->dev), "vaddr_to = %p\n", vaddr_to); + dev_info(&(dev->dev), "vaddr_to = %px\n", vaddr_to); dev_info(&(dev->dev), "dma_handle_to = %llx\n", (unsigned long long)dma_handle_to); /* iowrite32(DMA_BASE, mmio + IO_DMA_SRC);