Commit | Line | Data |
---|---|---|
09c434b8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
804defea | 2 | /* |
804defea | 3 | * Here's a sample kernel module showing the use of kprobes to dump a |
25239fd3 | 4 | * stack trace and selected registers when kernel_clone() is called. |
804defea AM |
5 | * |
6 | * For more information on theory of operation of kprobes, see | |
7f9a2357 | 7 | * Documentation/trace/kprobes.rst |
804defea AM |
8 | * |
9 | * You will see the trace data in /var/log/messages and on the console | |
25239fd3 | 10 | * whenever kernel_clone() is invoked to create a new process. |
804defea AM |
11 | */ |
12 | ||
db1ea668 TY |
13 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
14 | ||
804defea AM |
15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | |
17 | #include <linux/kprobes.h> | |
18 | ||
d04659ac | 19 | #define MAX_SYMBOL_LEN 64 |
25239fd3 | 20 | static char symbol[MAX_SYMBOL_LEN] = "kernel_clone"; |
d04659ac HS |
21 | module_param_string(symbol, symbol, sizeof(symbol), 0644); |
22 | ||
804defea AM |
23 | /* For each probe you need to allocate a kprobe structure */ |
24 | static struct kprobe kp = { | |
d04659ac | 25 | .symbol_name = symbol, |
804defea AM |
26 | }; |
27 | ||
28 | /* kprobe pre_handler: called just before the probed instruction is executed */ | |
d85eaa94 | 29 | static int __kprobes handler_pre(struct kprobe *p, struct pt_regs *regs) |
804defea AM |
30 | { |
31 | #ifdef CONFIG_X86 | |
db1ea668 | 32 | pr_info("<%s> p->addr = 0x%p, ip = %lx, flags = 0x%lx\n", |
ea9b5013 | 33 | p->symbol_name, p->addr, regs->ip, regs->flags); |
804defea AM |
34 | #endif |
35 | #ifdef CONFIG_PPC | |
db1ea668 | 36 | pr_info("<%s> p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx\n", |
ea9b5013 | 37 | p->symbol_name, p->addr, regs->nip, regs->msr); |
804defea | 38 | #endif |
8a149237 | 39 | #ifdef CONFIG_MIPS |
db1ea668 | 40 | pr_info("<%s> p->addr = 0x%p, epc = 0x%lx, status = 0x%lx\n", |
ea9b5013 | 41 | p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status); |
8a149237 | 42 | #endif |
af78cede | 43 | #ifdef CONFIG_ARM64 |
db1ea668 | 44 | pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, pstate = 0x%lx\n", |
af78cede SP |
45 | p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate); |
46 | #endif | |
6970613b | 47 | #ifdef CONFIG_ARM |
db1ea668 | 48 | pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, cpsr = 0x%lx\n", |
6970613b MK |
49 | p->symbol_name, p->addr, (long)regs->ARM_pc, (long)regs->ARM_cpsr); |
50 | #endif | |
8a07ac39 | 51 | #ifdef CONFIG_RISCV |
db1ea668 | 52 | pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, status = 0x%lx\n", |
8a07ac39 JZ |
53 | p->symbol_name, p->addr, regs->epc, regs->status); |
54 | #endif | |
e16c5dd5 | 55 | #ifdef CONFIG_S390 |
db1ea668 | 56 | pr_info("<%s> p->addr, 0x%p, ip = 0x%lx, flags = 0x%lx\n", |
e16c5dd5 JT |
57 | p->symbol_name, p->addr, regs->psw.addr, regs->flags); |
58 | #endif | |
804defea AM |
59 | |
60 | /* A dump_stack() here will give a stack backtrace */ | |
61 | return 0; | |
62 | } | |
63 | ||
64 | /* kprobe post_handler: called after the probed instruction is executed */ | |
d85eaa94 | 65 | static void __kprobes handler_post(struct kprobe *p, struct pt_regs *regs, |
804defea AM |
66 | unsigned long flags) |
67 | { | |
68 | #ifdef CONFIG_X86 | |
db1ea668 | 69 | pr_info("<%s> p->addr = 0x%p, flags = 0x%lx\n", |
ea9b5013 | 70 | p->symbol_name, p->addr, regs->flags); |
804defea AM |
71 | #endif |
72 | #ifdef CONFIG_PPC | |
db1ea668 | 73 | pr_info("<%s> p->addr = 0x%p, msr = 0x%lx\n", |
ea9b5013 | 74 | p->symbol_name, p->addr, regs->msr); |
804defea | 75 | #endif |
8a149237 | 76 | #ifdef CONFIG_MIPS |
db1ea668 | 77 | pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n", |
ea9b5013 | 78 | p->symbol_name, p->addr, regs->cp0_status); |
8a149237 | 79 | #endif |
af78cede | 80 | #ifdef CONFIG_ARM64 |
db1ea668 | 81 | pr_info("<%s> p->addr = 0x%p, pstate = 0x%lx\n", |
af78cede SP |
82 | p->symbol_name, p->addr, (long)regs->pstate); |
83 | #endif | |
6970613b | 84 | #ifdef CONFIG_ARM |
db1ea668 | 85 | pr_info("<%s> p->addr = 0x%p, cpsr = 0x%lx\n", |
6970613b MK |
86 | p->symbol_name, p->addr, (long)regs->ARM_cpsr); |
87 | #endif | |
8a07ac39 | 88 | #ifdef CONFIG_RISCV |
db1ea668 | 89 | pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n", |
8a07ac39 JZ |
90 | p->symbol_name, p->addr, regs->status); |
91 | #endif | |
e16c5dd5 | 92 | #ifdef CONFIG_S390 |
db1ea668 | 93 | pr_info("<%s> p->addr, 0x%p, flags = 0x%lx\n", |
e16c5dd5 JT |
94 | p->symbol_name, p->addr, regs->flags); |
95 | #endif | |
804defea AM |
96 | } |
97 | ||
804defea AM |
98 | static int __init kprobe_init(void) |
99 | { | |
100 | int ret; | |
101 | kp.pre_handler = handler_pre; | |
102 | kp.post_handler = handler_post; | |
804defea AM |
103 | |
104 | ret = register_kprobe(&kp); | |
105 | if (ret < 0) { | |
e708c148 | 106 | pr_err("register_kprobe failed, returned %d\n", ret); |
804defea AM |
107 | return ret; |
108 | } | |
e708c148 | 109 | pr_info("Planted kprobe at %p\n", kp.addr); |
804defea AM |
110 | return 0; |
111 | } | |
112 | ||
113 | static void __exit kprobe_exit(void) | |
114 | { | |
115 | unregister_kprobe(&kp); | |
e708c148 | 116 | pr_info("kprobe at %p unregistered\n", kp.addr); |
804defea AM |
117 | } |
118 | ||
119 | module_init(kprobe_init) | |
120 | module_exit(kprobe_exit) | |
121 | MODULE_LICENSE("GPL"); |