1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| char __license[] SEC("license") = "Dual MIT/GPL";
struct event {
u32 pid;
u8 line[256];
u8 mark;
};
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} events SEC(".maps");
// Force emitting struct event into the ELF.
const struct event *unused __attribute__((unused));
// 通过bpf-tail-call只能调用同类型的bpf函数
SEC("uretprobe/bash_readline_odd")
int uretprobe_bash_readline_odd(struct pt_regs *ctx){
struct event event = {};
event.pid = bpf_get_current_pid_tgid();
event.line[0] = 49;
event.mark = 5;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
return 0;
}
// 通过bpf-tail-call只能调用同类型的bpf函数
SEC("uretprobe/bash_readline_even")
int uretprobe_bash_readline_even(struct pt_regs *ctx){
struct event event = {};
event.pid = bpf_get_current_pid_tgid();
event.mark = 8;
event.line[0] = 50;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
return 0;
}
struct{
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
__uint(max_entries, 1024);
__array(values, int (void*));
} tail_jmp_table SEC(".maps") = {
.values = {
// 这里的id是可以在用户态通过map update来更新的。由此可以延伸出其他有意思的功能。这里从实际需求直接固定值了。
[135] = (void*)&uretprobe_bash_readline_odd,
[146] = (void*)&uretprobe_bash_readline_even,
},
};
SEC("uretprobe/bash_readline")
int uretprobe_bash_readline(struct pt_regs *ctx) {
struct event event = {};
event.pid = bpf_get_current_pid_tgid();
bpf_probe_read(&event.line, sizeof(event.line), (void *)PT_REGS_RC(ctx));
event.mark = 3;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
u8 line_length=0;
for(line_length=0; line_length<80; line_length++){
if(event.line[line_length] == 0){
break;
}
}
if (line_length % 2 == 0){
// 偶数调用 uretprobe_bash_readline_even
bpf_tail_call(ctx, &tail_jmp_table, 146);
}else{
// 奇数调用 uretprobe_bash_readline_odd
bpf_tail_call(ctx, &tail_jmp_table, 135);
}
return 0;
}
|