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 | ||
1e1fb420 TY |
19 | static char symbol[KSYM_NAME_LEN] = "kernel_clone"; |
20 | module_param_string(symbol, symbol, KSYM_NAME_LEN, 0644); | |
d04659ac | 21 | |
804defea AM |
22 | /* For each probe you need to allocate a kprobe structure */ |
23 | static struct kprobe kp = { | |
d04659ac | 24 | .symbol_name = symbol, |
804defea AM |
25 | }; |
26 | ||
27 | /* kprobe pre_handler: called just before the probed instruction is executed */ | |
d85eaa94 | 28 | static int __kprobes handler_pre(struct kprobe *p, struct pt_regs *regs) |
804defea AM |
29 | { |
30 | #ifdef CONFIG_X86 | |
db1ea668 | 31 | pr_info("<%s> p->addr = 0x%p, ip = %lx, flags = 0x%lx\n", |
ea9b5013 | 32 | p->symbol_name, p->addr, regs->ip, regs->flags); |
804defea AM |
33 | #endif |
34 | #ifdef CONFIG_PPC | |
db1ea668 | 35 | pr_info("<%s> p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx\n", |
ea9b5013 | 36 | p->symbol_name, p->addr, regs->nip, regs->msr); |
804defea | 37 | #endif |
8a149237 | 38 | #ifdef CONFIG_MIPS |
db1ea668 | 39 | pr_info("<%s> p->addr = 0x%p, epc = 0x%lx, status = 0x%lx\n", |
ea9b5013 | 40 | p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status); |
8a149237 | 41 | #endif |
af78cede | 42 | #ifdef CONFIG_ARM64 |
db1ea668 | 43 | pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, pstate = 0x%lx\n", |
af78cede SP |
44 | p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate); |
45 | #endif | |
6970613b | 46 | #ifdef CONFIG_ARM |
db1ea668 | 47 | pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, cpsr = 0x%lx\n", |
6970613b MK |
48 | p->symbol_name, p->addr, (long)regs->ARM_pc, (long)regs->ARM_cpsr); |
49 | #endif | |
8a07ac39 | 50 | #ifdef CONFIG_RISCV |
db1ea668 | 51 | pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, status = 0x%lx\n", |
8a07ac39 JZ |
52 | p->symbol_name, p->addr, regs->epc, regs->status); |
53 | #endif | |
e16c5dd5 | 54 | #ifdef CONFIG_S390 |
db1ea668 | 55 | pr_info("<%s> p->addr, 0x%p, ip = 0x%lx, flags = 0x%lx\n", |
e16c5dd5 JT |
56 | p->symbol_name, p->addr, regs->psw.addr, regs->flags); |
57 | #endif | |
a6484baa TY |
58 | #ifdef CONFIG_LOONGARCH |
59 | pr_info("<%s> p->addr = 0x%p, era = 0x%lx, estat = 0x%lx\n", | |
60 | p->symbol_name, p->addr, regs->csr_era, regs->csr_estat); | |
61 | #endif | |
804defea AM |
62 | |
63 | /* A dump_stack() here will give a stack backtrace */ | |
64 | return 0; | |
65 | } | |
66 | ||
67 | /* kprobe post_handler: called after the probed instruction is executed */ | |
d85eaa94 | 68 | static void __kprobes handler_post(struct kprobe *p, struct pt_regs *regs, |
804defea AM |
69 | unsigned long flags) |
70 | { | |
71 | #ifdef CONFIG_X86 | |
db1ea668 | 72 | pr_info("<%s> p->addr = 0x%p, flags = 0x%lx\n", |
ea9b5013 | 73 | p->symbol_name, p->addr, regs->flags); |
804defea AM |
74 | #endif |
75 | #ifdef CONFIG_PPC | |
db1ea668 | 76 | pr_info("<%s> p->addr = 0x%p, msr = 0x%lx\n", |
ea9b5013 | 77 | p->symbol_name, p->addr, regs->msr); |
804defea | 78 | #endif |
8a149237 | 79 | #ifdef CONFIG_MIPS |
db1ea668 | 80 | pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n", |
ea9b5013 | 81 | p->symbol_name, p->addr, regs->cp0_status); |
8a149237 | 82 | #endif |
af78cede | 83 | #ifdef CONFIG_ARM64 |
db1ea668 | 84 | pr_info("<%s> p->addr = 0x%p, pstate = 0x%lx\n", |
af78cede SP |
85 | p->symbol_name, p->addr, (long)regs->pstate); |
86 | #endif | |
6970613b | 87 | #ifdef CONFIG_ARM |
db1ea668 | 88 | pr_info("<%s> p->addr = 0x%p, cpsr = 0x%lx\n", |
6970613b MK |
89 | p->symbol_name, p->addr, (long)regs->ARM_cpsr); |
90 | #endif | |
8a07ac39 | 91 | #ifdef CONFIG_RISCV |
db1ea668 | 92 | pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n", |
8a07ac39 JZ |
93 | p->symbol_name, p->addr, regs->status); |
94 | #endif | |
e16c5dd5 | 95 | #ifdef CONFIG_S390 |
db1ea668 | 96 | pr_info("<%s> p->addr, 0x%p, flags = 0x%lx\n", |
e16c5dd5 JT |
97 | p->symbol_name, p->addr, regs->flags); |
98 | #endif | |
a6484baa TY |
99 | #ifdef CONFIG_LOONGARCH |
100 | pr_info("<%s> p->addr = 0x%p, estat = 0x%lx\n", | |
101 | p->symbol_name, p->addr, regs->csr_estat); | |
102 | #endif | |
804defea AM |
103 | } |
104 | ||
804defea AM |
105 | static int __init kprobe_init(void) |
106 | { | |
107 | int ret; | |
108 | kp.pre_handler = handler_pre; | |
109 | kp.post_handler = handler_post; | |
804defea AM |
110 | |
111 | ret = register_kprobe(&kp); | |
112 | if (ret < 0) { | |
e708c148 | 113 | pr_err("register_kprobe failed, returned %d\n", ret); |
804defea AM |
114 | return ret; |
115 | } | |
e708c148 | 116 | pr_info("Planted kprobe at %p\n", kp.addr); |
804defea AM |
117 | return 0; |
118 | } | |
119 | ||
120 | static void __exit kprobe_exit(void) | |
121 | { | |
122 | unregister_kprobe(&kp); | |
e708c148 | 123 | pr_info("kprobe at %p unregistered\n", kp.addr); |
804defea AM |
124 | } |
125 | ||
126 | module_init(kprobe_init) | |
127 | module_exit(kprobe_exit) | |
128 | MODULE_LICENSE("GPL"); |