mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
kprobe: update example with px
Going to try and upstream this later on
This commit is contained in:
28
README.adoc
28
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?
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user