Skip to content

Commit 0fd612b

Browse files
committed
lkm_exampe
1 parent 55d3ac2 commit 0fd612b

File tree

11 files changed

+435
-0
lines changed

11 files changed

+435
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,5 @@ modules.order
5050
Module.symvers
5151
Mkfile.old
5252
dkms.conf
53+
54+
.history

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
11. 内核uprobe trace用户态、地址监控
1414
12. tracepoints动态监控用态函数
1515
13. eBPF trace
16+
14. linux内核:通过创建设备文件与用户态进行通信

android-kernel/1.txt

Whitespace-only changes.

android-kernel/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# builds the kprobes example kernel modules;
2+
# then to use one (as root): insmod <module_name.ko>
3+
4+
obj-$(CONFIG_SAMPLE_KPROBES) += kprobe_example.o jprobe_example.o
5+
obj-$(CONFIG_SAMPLE_KRETPROBES) += kretprobe_example.o

android-kernel/jprobe_example.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Here's a sample kernel module showing the use of jprobes to dump
3+
* the arguments of _do_fork().
4+
*
5+
* For more information on theory of operation of jprobes, see
6+
* Documentation/kprobes.txt
7+
*
8+
* Build and insert the kernel module as done in the kprobe example.
9+
* You will see the trace data in /var/log/messages and on the
10+
* console whenever _do_fork() is invoked to create a new process.
11+
* (Some messages may be suppressed if syslogd is configured to
12+
* eliminate duplicate messages.)
13+
*/
14+
15+
#include <linux/kernel.h>
16+
#include <linux/module.h>
17+
#include <linux/kprobes.h>
18+
19+
/*
20+
* Jumper probe for _do_fork.
21+
* Mirror principle enables access to arguments of the probed routine
22+
* from the probe handler.
23+
*/
24+
25+
/* Proxy routine having the same arguments as actual _do_fork() routine */
26+
static long j_do_fork(unsigned long clone_flags, unsigned long stack_start,
27+
unsigned long stack_size, int __user *parent_tidptr,
28+
int __user *child_tidptr)
29+
{
30+
pr_info("jprobe: clone_flags = 0x%lx, stack_start = 0x%lx "
31+
"stack_size = 0x%lx\n", clone_flags, stack_start, stack_size);
32+
33+
/* Always end with a call to jprobe_return(). */
34+
jprobe_return();
35+
return 0;
36+
}
37+
38+
static struct jprobe my_jprobe = {
39+
.entry = j_do_fork,
40+
.kp = {
41+
.symbol_name = "_do_fork",
42+
},
43+
};
44+
45+
static int __init jprobe_init(void)
46+
{
47+
int ret;
48+
49+
ret = register_jprobe(&my_jprobe);
50+
if (ret < 0) {
51+
printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
52+
return -1;
53+
}
54+
printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
55+
my_jprobe.kp.addr, my_jprobe.entry);
56+
return 0;
57+
}
58+
59+
static void __exit jprobe_exit(void)
60+
{
61+
unregister_jprobe(&my_jprobe);
62+
printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr);
63+
}
64+
65+
module_init(jprobe_init)
66+
module_exit(jprobe_exit)
67+
MODULE_LICENSE("GPL");

android-kernel/kprobe_example.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* NOTE: This example is works on x86 and powerpc.
3+
* Here's a sample kernel module showing the use of kprobes to dump a
4+
* stack trace and selected registers when _do_fork() is called.
5+
*
6+
* For more information on theory of operation of kprobes, see
7+
* Documentation/kprobes.txt
8+
*
9+
* You will see the trace data in /var/log/messages and on the console
10+
* whenever _do_fork() is invoked to create a new process.
11+
*/
12+
13+
#include <linux/kernel.h>
14+
#include <linux/module.h>
15+
#include <linux/kprobes.h>
16+
17+
/* For each probe you need to allocate a kprobe structure */
18+
static struct kprobe kp = {
19+
.symbol_name = "_do_fork",
20+
};
21+
22+
/* kprobe pre_handler: called just before the probed instruction is executed */
23+
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
24+
{
25+
#ifdef CONFIG_X86
26+
printk(KERN_INFO "pre_handler: p->addr = 0x%p, ip = %lx,"
27+
" flags = 0x%lx\n",
28+
p->addr, regs->ip, regs->flags);
29+
#endif
30+
#ifdef CONFIG_PPC
31+
printk(KERN_INFO "pre_handler: p->addr = 0x%p, nip = 0x%lx,"
32+
" msr = 0x%lx\n",
33+
p->addr, regs->nip, regs->msr);
34+
#endif
35+
#ifdef CONFIG_MIPS
36+
printk(KERN_INFO "pre_handler: p->addr = 0x%p, epc = 0x%lx,"
37+
" status = 0x%lx\n",
38+
p->addr, regs->cp0_epc, regs->cp0_status);
39+
#endif
40+
#ifdef CONFIG_TILEGX
41+
printk(KERN_INFO "pre_handler: p->addr = 0x%p, pc = 0x%lx,"
42+
" ex1 = 0x%lx\n",
43+
p->addr, regs->pc, regs->ex1);
44+
#endif
45+
#ifdef CONFIG_ARM64
46+
pr_info("<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx,"
47+
" pstate = 0x%lx\n",
48+
p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate);
49+
#endif
50+
51+
/* A dump_stack() here will give a stack backtrace */
52+
return 0;
53+
}
54+
55+
/* kprobe post_handler: called after the probed instruction is executed */
56+
static void handler_post(struct kprobe *p, struct pt_regs *regs,
57+
unsigned long flags)
58+
{
59+
#ifdef CONFIG_X86
60+
printk(KERN_INFO "post_handler: p->addr = 0x%p, flags = 0x%lx\n",
61+
p->addr, regs->flags);
62+
#endif
63+
#ifdef CONFIG_PPC
64+
printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\n",
65+
p->addr, regs->msr);
66+
#endif
67+
#ifdef CONFIG_MIPS
68+
printk(KERN_INFO "post_handler: p->addr = 0x%p, status = 0x%lx\n",
69+
p->addr, regs->cp0_status);
70+
#endif
71+
#ifdef CONFIG_TILEGX
72+
printk(KERN_INFO "post_handler: p->addr = 0x%p, ex1 = 0x%lx\n",
73+
p->addr, regs->ex1);
74+
#endif
75+
#ifdef CONFIG_ARM64
76+
pr_info("<%s> post_handler: p->addr = 0x%p, pstate = 0x%lx\n",
77+
p->symbol_name, p->addr, (long)regs->pstate);
78+
#endif
79+
}
80+
81+
/*
82+
* fault_handler: this is called if an exception is generated for any
83+
* instruction within the pre- or post-handler, or when Kprobes
84+
* single-steps the probed instruction.
85+
*/
86+
static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
87+
{
88+
printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn",
89+
p->addr, trapnr);
90+
/* Return 0 because we don't handle the fault. */
91+
return 0;
92+
}
93+
94+
static int __init kprobe_init(void)
95+
{
96+
int ret;
97+
kp.pre_handler = handler_pre;
98+
kp.post_handler = handler_post;
99+
kp.fault_handler = handler_fault;
100+
101+
ret = register_kprobe(&kp);
102+
if (ret < 0) {
103+
printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);
104+
return ret;
105+
}
106+
printk(KERN_INFO "Planted kprobe at %p\n", kp.addr);
107+
return 0;
108+
}
109+
110+
static void __exit kprobe_exit(void)
111+
{
112+
unregister_kprobe(&kp);
113+
printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
114+
}
115+
116+
module_init(kprobe_init)
117+
module_exit(kprobe_exit)
118+
MODULE_LICENSE("GPL");

android-kernel/kretprobe_example.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* kretprobe_example.c
3+
*
4+
* Here's a sample kernel module showing the use of return probes to
5+
* report the return value and total time taken for probed function
6+
* to run.
7+
*
8+
* usage: insmod kretprobe_example.ko func=<func_name>
9+
*
10+
* If no func_name is specified, _do_fork is instrumented
11+
*
12+
* For more information on theory of operation of kretprobes, see
13+
* Documentation/kprobes.txt
14+
*
15+
* Build and insert the kernel module as done in the kprobe example.
16+
* You will see the trace data in /var/log/messages and on the console
17+
* whenever the probed function returns. (Some messages may be suppressed
18+
* if syslogd is configured to eliminate duplicate messages.)
19+
*/
20+
21+
#include <linux/kernel.h>
22+
#include <linux/module.h>
23+
#include <linux/kprobes.h>
24+
#include <linux/ktime.h>
25+
#include <linux/limits.h>
26+
#include <linux/sched.h>
27+
28+
static char func_name[NAME_MAX] = "_do_fork";
29+
module_param_string(func, func_name, NAME_MAX, S_IRUGO);
30+
MODULE_PARM_DESC(func, "Function to kretprobe; this module will report the"
31+
" function's execution time");
32+
33+
/* per-instance private data */
34+
struct my_data {
35+
ktime_t entry_stamp;
36+
};
37+
38+
/* Here we use the entry_hanlder to timestamp function entry */
39+
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
40+
{
41+
struct my_data *data;
42+
43+
if (!current->mm)
44+
return 1; /* Skip kernel threads */
45+
46+
data = (struct my_data *)ri->data;
47+
data->entry_stamp = ktime_get();
48+
return 0;
49+
}
50+
51+
/*
52+
* Return-probe handler: Log the return value and duration. Duration may turn
53+
* out to be zero consistently, depending upon the granularity of time
54+
* accounting on the platform.
55+
*/
56+
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
57+
{
58+
int retval = regs_return_value(regs);
59+
struct my_data *data = (struct my_data *)ri->data;
60+
s64 delta;
61+
ktime_t now;
62+
63+
now = ktime_get();
64+
delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
65+
printk(KERN_INFO "%s returned %d and took %lld ns to execute\n",
66+
func_name, retval, (long long)delta);
67+
return 0;
68+
}
69+
70+
static struct kretprobe my_kretprobe = {
71+
.handler = ret_handler,
72+
.entry_handler = entry_handler,
73+
.data_size = sizeof(struct my_data),
74+
/* Probe up to 20 instances concurrently. */
75+
.maxactive = 20,
76+
};
77+
78+
static int __init kretprobe_init(void)
79+
{
80+
int ret;
81+
82+
my_kretprobe.kp.symbol_name = func_name;
83+
ret = register_kretprobe(&my_kretprobe);
84+
if (ret < 0) {
85+
printk(KERN_INFO "register_kretprobe failed, returned %d\n",
86+
ret);
87+
return -1;
88+
}
89+
printk(KERN_INFO "Planted return probe at %s: %p\n",
90+
my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr);
91+
return 0;
92+
}
93+
94+
static void __exit kretprobe_exit(void)
95+
{
96+
unregister_kretprobe(&my_kretprobe);
97+
printk(KERN_INFO "kretprobe at %p unregistered\n",
98+
my_kretprobe.kp.addr);
99+
100+
/* nmissed > 0 suggests that maxactive was set too low. */
101+
printk(KERN_INFO "Missed probing %d instances of %s\n",
102+
my_kretprobe.nmissed, my_kretprobe.kp.symbol_name);
103+
}
104+
105+
module_init(kretprobe_init)
106+
module_exit(kretprobe_exit)
107+
MODULE_LICENSE("GPL");

linux-kernel/lkm_example/Makefile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
obj-m += lkm_example.o
2+
all:
3+
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
4+
clean:
5+
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
6+
test:
7+
# We put a — in front of the rmmod command to tell make to ignore
8+
# an error in case the module isn’t loaded.
9+
sudo rmmod lkm_example
10+
# Clear the kernel log without echo
11+
sudo dmesg -C
12+
# Insert the module
13+
sudo insmod lkm_example.ko
14+
# Display the kernel log
15+
dmesg

linux-kernel/lkm_example/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# lkm_example
2+
## 例子功能:通过创建设备文件与用户态进行通信
3+
在 Ubuntu 中需要运行:
4+
5+
```
6+
apt-get install build-essential linux-headers-`uname -r`
7+
```
8+
9+
# 测试
10+
make test
11+
12+
# 引用
13+
|https://www.oschina.net/translate/writing-a-simple-linux-kernel-module

0 commit comments

Comments
 (0)