xref: /linux/samples/kprobes/kprobe_example.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2804defeaSAnanth N Mavinakayanahalli /*
3804defeaSAnanth N Mavinakayanahalli  * Here's a sample kernel module showing the use of kprobes to dump a
425239fd3SChristian Brauner  * stack trace and selected registers when kernel_clone() is called.
5804defeaSAnanth N Mavinakayanahalli  *
6804defeaSAnanth N Mavinakayanahalli  * For more information on theory of operation of kprobes, see
77f9a2357SMauro Carvalho Chehab  * Documentation/trace/kprobes.rst
8804defeaSAnanth N Mavinakayanahalli  *
9804defeaSAnanth N Mavinakayanahalli  * You will see the trace data in /var/log/messages and on the console
1025239fd3SChristian Brauner  * whenever kernel_clone() is invoked to create a new process.
11804defeaSAnanth N Mavinakayanahalli  */
12804defeaSAnanth N Mavinakayanahalli 
13db1ea668STiezhu Yang #define pr_fmt(fmt) "%s: " fmt, __func__
14db1ea668STiezhu Yang 
15804defeaSAnanth N Mavinakayanahalli #include <linux/kernel.h>
16804defeaSAnanth N Mavinakayanahalli #include <linux/module.h>
17804defeaSAnanth N Mavinakayanahalli #include <linux/kprobes.h>
18804defeaSAnanth N Mavinakayanahalli 
191e1fb420STiezhu Yang static char symbol[KSYM_NAME_LEN] = "kernel_clone";
201e1fb420STiezhu Yang module_param_string(symbol, symbol, KSYM_NAME_LEN, 0644);
21d04659acSHuang Shijie 
22804defeaSAnanth N Mavinakayanahalli /* For each probe you need to allocate a kprobe structure */
23804defeaSAnanth N Mavinakayanahalli static struct kprobe kp = {
24d04659acSHuang Shijie 	.symbol_name	= symbol,
25804defeaSAnanth N Mavinakayanahalli };
26804defeaSAnanth N Mavinakayanahalli 
27804defeaSAnanth N Mavinakayanahalli /* kprobe pre_handler: called just before the probed instruction is executed */
handler_pre(struct kprobe * p,struct pt_regs * regs)28d85eaa94SMasami Hiramatsu static int __kprobes handler_pre(struct kprobe *p, struct pt_regs *regs)
29804defeaSAnanth N Mavinakayanahalli {
30804defeaSAnanth N Mavinakayanahalli #ifdef CONFIG_X86
31db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, ip = %lx, flags = 0x%lx\n",
32ea9b5013SHuang Shijie 		p->symbol_name, p->addr, regs->ip, regs->flags);
33804defeaSAnanth N Mavinakayanahalli #endif
34804defeaSAnanth N Mavinakayanahalli #ifdef CONFIG_PPC
35db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx\n",
36ea9b5013SHuang Shijie 		p->symbol_name, p->addr, regs->nip, regs->msr);
37804defeaSAnanth N Mavinakayanahalli #endif
388a149237SDavid Daney #ifdef CONFIG_MIPS
39db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, epc = 0x%lx, status = 0x%lx\n",
40ea9b5013SHuang Shijie 		p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status);
418a149237SDavid Daney #endif
42af78cedeSSandeepa Prabhu #ifdef CONFIG_ARM64
43db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, pstate = 0x%lx\n",
44af78cedeSSandeepa Prabhu 		p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate);
45af78cedeSSandeepa Prabhu #endif
466970613bSMarc Koderer #ifdef CONFIG_ARM
47db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, cpsr = 0x%lx\n",
486970613bSMarc Koderer 		p->symbol_name, p->addr, (long)regs->ARM_pc, (long)regs->ARM_cpsr);
496970613bSMarc Koderer #endif
508a07ac39SJisheng Zhang #ifdef CONFIG_RISCV
51db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, status = 0x%lx\n",
528a07ac39SJisheng Zhang 		p->symbol_name, p->addr, regs->epc, regs->status);
538a07ac39SJisheng Zhang #endif
54e16c5dd5SJohannes Thumshirn #ifdef CONFIG_S390
55db1ea668STiezhu Yang 	pr_info("<%s> p->addr, 0x%p, ip = 0x%lx, flags = 0x%lx\n",
56e16c5dd5SJohannes Thumshirn 		p->symbol_name, p->addr, regs->psw.addr, regs->flags);
57e16c5dd5SJohannes Thumshirn #endif
58a6484baaSTiezhu Yang #ifdef CONFIG_LOONGARCH
59a6484baaSTiezhu Yang 	pr_info("<%s> p->addr = 0x%p, era = 0x%lx, estat = 0x%lx\n",
60a6484baaSTiezhu Yang 		p->symbol_name, p->addr, regs->csr_era, regs->csr_estat);
61a6484baaSTiezhu Yang #endif
62804defeaSAnanth N Mavinakayanahalli 
63804defeaSAnanth N Mavinakayanahalli 	/* A dump_stack() here will give a stack backtrace */
64804defeaSAnanth N Mavinakayanahalli 	return 0;
65804defeaSAnanth N Mavinakayanahalli }
66804defeaSAnanth N Mavinakayanahalli 
67804defeaSAnanth N Mavinakayanahalli /* kprobe post_handler: called after the probed instruction is executed */
handler_post(struct kprobe * p,struct pt_regs * regs,unsigned long flags)68d85eaa94SMasami Hiramatsu static void __kprobes handler_post(struct kprobe *p, struct pt_regs *regs,
69804defeaSAnanth N Mavinakayanahalli 				unsigned long flags)
70804defeaSAnanth N Mavinakayanahalli {
71804defeaSAnanth N Mavinakayanahalli #ifdef CONFIG_X86
72db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, flags = 0x%lx\n",
73ea9b5013SHuang Shijie 		p->symbol_name, p->addr, regs->flags);
74804defeaSAnanth N Mavinakayanahalli #endif
75804defeaSAnanth N Mavinakayanahalli #ifdef CONFIG_PPC
76db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, msr = 0x%lx\n",
77ea9b5013SHuang Shijie 		p->symbol_name, p->addr, regs->msr);
78804defeaSAnanth N Mavinakayanahalli #endif
798a149237SDavid Daney #ifdef CONFIG_MIPS
80db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n",
81ea9b5013SHuang Shijie 		p->symbol_name, p->addr, regs->cp0_status);
828a149237SDavid Daney #endif
83af78cedeSSandeepa Prabhu #ifdef CONFIG_ARM64
84db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, pstate = 0x%lx\n",
85af78cedeSSandeepa Prabhu 		p->symbol_name, p->addr, (long)regs->pstate);
86af78cedeSSandeepa Prabhu #endif
876970613bSMarc Koderer #ifdef CONFIG_ARM
88db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, cpsr = 0x%lx\n",
896970613bSMarc Koderer 		p->symbol_name, p->addr, (long)regs->ARM_cpsr);
906970613bSMarc Koderer #endif
918a07ac39SJisheng Zhang #ifdef CONFIG_RISCV
92db1ea668STiezhu Yang 	pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n",
938a07ac39SJisheng Zhang 		p->symbol_name, p->addr, regs->status);
948a07ac39SJisheng Zhang #endif
95e16c5dd5SJohannes Thumshirn #ifdef CONFIG_S390
96db1ea668STiezhu Yang 	pr_info("<%s> p->addr, 0x%p, flags = 0x%lx\n",
97e16c5dd5SJohannes Thumshirn 		p->symbol_name, p->addr, regs->flags);
98e16c5dd5SJohannes Thumshirn #endif
99a6484baaSTiezhu Yang #ifdef CONFIG_LOONGARCH
100a6484baaSTiezhu Yang 	pr_info("<%s> p->addr = 0x%p, estat = 0x%lx\n",
101a6484baaSTiezhu Yang 		p->symbol_name, p->addr, regs->csr_estat);
102a6484baaSTiezhu Yang #endif
103804defeaSAnanth N Mavinakayanahalli }
104804defeaSAnanth N Mavinakayanahalli 
kprobe_init(void)105804defeaSAnanth N Mavinakayanahalli static int __init kprobe_init(void)
106804defeaSAnanth N Mavinakayanahalli {
107804defeaSAnanth N Mavinakayanahalli 	int ret;
108804defeaSAnanth N Mavinakayanahalli 	kp.pre_handler = handler_pre;
109804defeaSAnanth N Mavinakayanahalli 	kp.post_handler = handler_post;
110804defeaSAnanth N Mavinakayanahalli 
111804defeaSAnanth N Mavinakayanahalli 	ret = register_kprobe(&kp);
112804defeaSAnanth N Mavinakayanahalli 	if (ret < 0) {
113e708c148SHuang Shijie 		pr_err("register_kprobe failed, returned %d\n", ret);
114804defeaSAnanth N Mavinakayanahalli 		return ret;
115804defeaSAnanth N Mavinakayanahalli 	}
116e708c148SHuang Shijie 	pr_info("Planted kprobe at %p\n", kp.addr);
117804defeaSAnanth N Mavinakayanahalli 	return 0;
118804defeaSAnanth N Mavinakayanahalli }
119804defeaSAnanth N Mavinakayanahalli 
kprobe_exit(void)120804defeaSAnanth N Mavinakayanahalli static void __exit kprobe_exit(void)
121804defeaSAnanth N Mavinakayanahalli {
122804defeaSAnanth N Mavinakayanahalli 	unregister_kprobe(&kp);
123e708c148SHuang Shijie 	pr_info("kprobe at %p unregistered\n", kp.addr);
124804defeaSAnanth N Mavinakayanahalli }
125804defeaSAnanth N Mavinakayanahalli 
126804defeaSAnanth N Mavinakayanahalli module_init(kprobe_init)
127804defeaSAnanth N Mavinakayanahalli module_exit(kprobe_exit)
128*1b3c86eeSJeff Johnson MODULE_DESCRIPTION("sample kernel module showing the use of kprobes");
129804defeaSAnanth N Mavinakayanahalli MODULE_LICENSE("GPL");
130