blob: f991a66b5b022a83c789d544b43a9be89be5a172 [file] [log] [blame]
Thomas Gleixner09c434b2019-05-19 13:08:20 +01001// SPDX-License-Identifier: GPL-2.0-only
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -08002/*
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -08003 * Here's a sample kernel module showing the use of kprobes to dump a
Christian Brauner25239fd2020-08-19 12:46:52 +02004 * stack trace and selected registers when kernel_clone() is called.
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -08005 *
6 * For more information on theory of operation of kprobes, see
Mauro Carvalho Chehab7f9a2352020-09-09 16:10:37 +02007 * Documentation/trace/kprobes.rst
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -08008 *
9 * You will see the trace data in /var/log/messages and on the console
Christian Brauner25239fd2020-08-19 12:46:52 +020010 * whenever kernel_clone() is invoked to create a new process.
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080011 */
12
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080013#define pr_fmt(fmt) "%s: " fmt, __func__
14
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080015#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/kprobes.h>
18
Huang Shijied04659a2016-05-20 17:04:33 -070019#define MAX_SYMBOL_LEN 64
Christian Brauner25239fd2020-08-19 12:46:52 +020020static char symbol[MAX_SYMBOL_LEN] = "kernel_clone";
Huang Shijied04659a2016-05-20 17:04:33 -070021module_param_string(symbol, symbol, sizeof(symbol), 0644);
22
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080023/* For each probe you need to allocate a kprobe structure */
24static struct kprobe kp = {
Huang Shijied04659a2016-05-20 17:04:33 -070025 .symbol_name = symbol,
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080026};
27
28/* kprobe pre_handler: called just before the probed instruction is executed */
Masami Hiramatsud85eaa92020-03-26 23:50:11 +090029static int __kprobes handler_pre(struct kprobe *p, struct pt_regs *regs)
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080030{
31#ifdef CONFIG_X86
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080032 pr_info("<%s> p->addr = 0x%p, ip = %lx, flags = 0x%lx\n",
Huang Shijieea9b5012016-05-20 17:04:36 -070033 p->symbol_name, p->addr, regs->ip, regs->flags);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080034#endif
35#ifdef CONFIG_PPC
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080036 pr_info("<%s> p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx\n",
Huang Shijieea9b5012016-05-20 17:04:36 -070037 p->symbol_name, p->addr, regs->nip, regs->msr);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080038#endif
David Daney8a149232010-08-03 11:22:21 -070039#ifdef CONFIG_MIPS
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080040 pr_info("<%s> p->addr = 0x%p, epc = 0x%lx, status = 0x%lx\n",
Huang Shijieea9b5012016-05-20 17:04:36 -070041 p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status);
David Daney8a149232010-08-03 11:22:21 -070042#endif
Sandeepa Prabhuaf78ced2016-07-08 12:35:54 -040043#ifdef CONFIG_ARM64
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080044 pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, pstate = 0x%lx\n",
Sandeepa Prabhuaf78ced2016-07-08 12:35:54 -040045 p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate);
46#endif
Marc Koderer69706132021-01-12 16:40:54 +010047#ifdef CONFIG_ARM
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080048 pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, cpsr = 0x%lx\n",
Marc Koderer69706132021-01-12 16:40:54 +010049 p->symbol_name, p->addr, (long)regs->ARM_pc, (long)regs->ARM_cpsr);
50#endif
Jisheng Zhang8a07ac32021-03-30 02:04:16 +080051#ifdef CONFIG_RISCV
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080052 pr_info("<%s> p->addr = 0x%p, pc = 0x%lx, status = 0x%lx\n",
Jisheng Zhang8a07ac32021-03-30 02:04:16 +080053 p->symbol_name, p->addr, regs->epc, regs->status);
54#endif
Johannes Thumshirne16c5dd2017-09-14 14:11:15 +020055#ifdef CONFIG_S390
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080056 pr_info("<%s> p->addr, 0x%p, ip = 0x%lx, flags = 0x%lx\n",
Johannes Thumshirne16c5dd2017-09-14 14:11:15 +020057 p->symbol_name, p->addr, regs->psw.addr, regs->flags);
58#endif
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080059
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 */
Masami Hiramatsud85eaa92020-03-26 23:50:11 +090065static void __kprobes handler_post(struct kprobe *p, struct pt_regs *regs,
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080066 unsigned long flags)
67{
68#ifdef CONFIG_X86
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080069 pr_info("<%s> p->addr = 0x%p, flags = 0x%lx\n",
Huang Shijieea9b5012016-05-20 17:04:36 -070070 p->symbol_name, p->addr, regs->flags);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080071#endif
72#ifdef CONFIG_PPC
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080073 pr_info("<%s> p->addr = 0x%p, msr = 0x%lx\n",
Huang Shijieea9b5012016-05-20 17:04:36 -070074 p->symbol_name, p->addr, regs->msr);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080075#endif
David Daney8a149232010-08-03 11:22:21 -070076#ifdef CONFIG_MIPS
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080077 pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n",
Huang Shijieea9b5012016-05-20 17:04:36 -070078 p->symbol_name, p->addr, regs->cp0_status);
David Daney8a149232010-08-03 11:22:21 -070079#endif
Sandeepa Prabhuaf78ced2016-07-08 12:35:54 -040080#ifdef CONFIG_ARM64
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080081 pr_info("<%s> p->addr = 0x%p, pstate = 0x%lx\n",
Sandeepa Prabhuaf78ced2016-07-08 12:35:54 -040082 p->symbol_name, p->addr, (long)regs->pstate);
83#endif
Marc Koderer69706132021-01-12 16:40:54 +010084#ifdef CONFIG_ARM
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080085 pr_info("<%s> p->addr = 0x%p, cpsr = 0x%lx\n",
Marc Koderer69706132021-01-12 16:40:54 +010086 p->symbol_name, p->addr, (long)regs->ARM_cpsr);
87#endif
Jisheng Zhang8a07ac32021-03-30 02:04:16 +080088#ifdef CONFIG_RISCV
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080089 pr_info("<%s> p->addr = 0x%p, status = 0x%lx\n",
Jisheng Zhang8a07ac32021-03-30 02:04:16 +080090 p->symbol_name, p->addr, regs->status);
91#endif
Johannes Thumshirne16c5dd2017-09-14 14:11:15 +020092#ifdef CONFIG_S390
Tiezhu Yangdb1ea662021-05-17 10:21:23 +080093 pr_info("<%s> p->addr, 0x%p, flags = 0x%lx\n",
Johannes Thumshirne16c5dd2017-09-14 14:11:15 +020094 p->symbol_name, p->addr, regs->flags);
95#endif
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080096}
97
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -080098static int __init kprobe_init(void)
99{
100 int ret;
101 kp.pre_handler = handler_pre;
102 kp.post_handler = handler_post;
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -0800103
104 ret = register_kprobe(&kp);
105 if (ret < 0) {
Huang Shijiee708c142016-08-03 13:46:03 -0700106 pr_err("register_kprobe failed, returned %d\n", ret);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -0800107 return ret;
108 }
Huang Shijiee708c142016-08-03 13:46:03 -0700109 pr_info("Planted kprobe at %p\n", kp.addr);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -0800110 return 0;
111}
112
113static void __exit kprobe_exit(void)
114{
115 unregister_kprobe(&kp);
Huang Shijiee708c142016-08-03 13:46:03 -0700116 pr_info("kprobe at %p unregistered\n", kp.addr);
Ananth N Mavinakayanahalli804defe2008-03-04 14:28:38 -0800117}
118
119module_init(kprobe_init)
120module_exit(kprobe_exit)
121MODULE_LICENSE("GPL");