inspektor-gadget

Форк
0
250 строк · 6.0 Кб
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/* Copyright (c) 2020 Wenbo Zhang */
3
#include <vmlinux.h>
4
#include <bpf/bpf_helpers.h>
5
#include <bpf/bpf_core_read.h>
6
#include <bpf/bpf_tracing.h>
7
#include "fsslower.h"
8
#include <gadget/mntns_filter.h>
9

10
#define MAX_ENTRIES 8192
11

12
const volatile pid_t target_pid = 0;
13
const volatile __u64 min_lat_ns = 0;
14

15
// we need this to make sure the compiler doesn't remove our struct
16
const struct event *unusedevent __attribute__((unused));
17

18
struct data_key {
19
	__u32 tid;
20
	/*
21
	 * We need to take into account the operation to avoid losing some of
22
	 * them.
23
	 * Indeed, it is possible to enter statfs syscall while already being in
24
	 * an open one.
25
	 */
26
	enum fs_file_op op;
27
};
28

29
struct data {
30
	__u64 ts;
31
	loff_t start;
32
	loff_t end;
33
	struct dentry *dentry;
34
};
35

36
struct {
37
	__uint(type, BPF_MAP_TYPE_HASH);
38
	__uint(max_entries, MAX_ENTRIES);
39
	__type(key, struct data_key);
40
	__type(value, struct data);
41
} starts SEC(".maps");
42

43
struct {
44
	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
45
	__uint(key_size, sizeof(__u32));
46
	__uint(value_size, sizeof(__u32));
47
} events SEC(".maps");
48

49
static int probe_entry(struct dentry *dentry, enum fs_file_op op, loff_t start,
50
		       loff_t end)
51
{
52
	__u64 pid_tgid = bpf_get_current_pid_tgid();
53
	__u32 pid = pid_tgid >> 32;
54
	__u32 tid = (__u32)pid_tgid;
55
	struct data data;
56
	struct data_key key = { .tid = tid, .op = op };
57
	u64 mntns_id;
58

59
	if (!dentry)
60
		return 0;
61

62
	// TODO: Enabling this conditional causes an error while loading the program
63
	// invalid argument: number of funcs in func_info doesn't match number of subprogs
64
	//if (target_pid && target_pid != pid)
65
	//	return 0;
66

67
	mntns_id = gadget_get_mntns_id();
68

69
	if (gadget_should_discard_mntns_id(mntns_id))
70
		return 0;
71

72
	data.ts = bpf_ktime_get_ns();
73
	data.start = start;
74
	data.end = end;
75
	data.dentry = dentry;
76
	bpf_map_update_elem(&starts, &key, &data, BPF_ANY);
77
	return 0;
78
}
79

80
static int probe_exit(void *ctx, enum fs_file_op op, ssize_t size)
81
{
82
	__u64 pid_tgid = bpf_get_current_pid_tgid();
83
	__u32 pid = pid_tgid >> 32;
84
	__u32 tid = (__u32)pid_tgid;
85
	__u64 end_ns, delta_ns;
86
	const __u8 *file_name;
87
	struct data *datap;
88
	struct event event = {};
89
	struct data_key key = { .tid = tid, .op = op };
90
	struct dentry *dentry;
91
	u64 mntns_id;
92

93
	//if (target_pid && target_pid != pid)
94
	//	return 0;
95

96
	datap = bpf_map_lookup_elem(&starts, &key);
97
	if (!datap)
98
		return 0;
99

100
	bpf_map_delete_elem(&starts, &key);
101

102
	end_ns = bpf_ktime_get_ns();
103
	delta_ns = end_ns - datap->ts;
104
	if (delta_ns <= min_lat_ns)
105
		return 0;
106

107
	event.delta_us = delta_ns / 1000;
108
	event.end_ns = end_ns;
109
	event.offset = datap->start;
110
	if (op != F_FSYNC)
111
		event.size = size;
112
	else
113
		event.size = datap->end - datap->start;
114
	event.pid = pid;
115
	event.op = op;
116
	event.mntns_id = gadget_get_mntns_id();
117
	event.timestamp = bpf_ktime_get_boot_ns();
118
	dentry = datap->dentry;
119
	file_name = BPF_CORE_READ(dentry, d_name.name);
120
	bpf_probe_read_kernel_str(&event.file, sizeof(event.file), file_name);
121
	bpf_get_current_comm(&event.task, sizeof(event.task));
122
	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event,
123
			      sizeof(event));
124
	return 0;
125
}
126

127
SEC("kprobe/dummy_file_read")
128
int BPF_KPROBE(ig_fssl_read_e, struct kiocb *iocb)
129
{
130
	struct dentry *dentry = BPF_CORE_READ(iocb, ki_filp, f_path.dentry);
131
	loff_t start = BPF_CORE_READ(iocb, ki_pos);
132

133
	return probe_entry(dentry, F_READ, start, 0);
134
}
135

136
SEC("kretprobe/dummy_file_read")
137
int BPF_KRETPROBE(ig_fssl_read_x, ssize_t ret)
138
{
139
	return probe_exit(ctx, F_READ, ret);
140
}
141

142
SEC("kprobe/dummy_file_write")
143
int BPF_KPROBE(ig_fssl_wr_e, struct kiocb *iocb)
144
{
145
	struct dentry *dentry = BPF_CORE_READ(iocb, ki_filp, f_path.dentry);
146
	loff_t start = BPF_CORE_READ(iocb, ki_pos);
147

148
	return probe_entry(dentry, F_WRITE, start, 0);
149
}
150

151
SEC("kretprobe/dummy_file_write")
152
int BPF_KRETPROBE(ig_fssl_wr_x, ssize_t ret)
153
{
154
	return probe_exit(ctx, F_WRITE, ret);
155
}
156

157
SEC("kprobe/dummy_file_open")
158
int BPF_KPROBE(ig_fssl_open_e, struct inode *inode, struct file *file)
159
{
160
	struct dentry *dentry = BPF_CORE_READ(file, f_path.dentry);
161
	return probe_entry(dentry, F_OPEN, 0, 0);
162
}
163

164
SEC("kretprobe/dummy_file_open")
165
int BPF_KRETPROBE(ig_fssl_open_x)
166
{
167
	return probe_exit(ctx, F_OPEN, 0);
168
}
169

170
SEC("kprobe/dummy_file_sync")
171
int BPF_KPROBE(ig_fssl_sync_e, struct file *file, loff_t start, loff_t end)
172
{
173
	struct dentry *dentry = BPF_CORE_READ(file, f_path.dentry);
174
	return probe_entry(dentry, F_FSYNC, start, end);
175
}
176

177
SEC("kretprobe/dummy_file_sync")
178
int BPF_KRETPROBE(ig_fssl_sync_x)
179
{
180
	return probe_exit(ctx, F_FSYNC, 0);
181
}
182

183
SEC("kprobe/dummy_file_statfs")
184
int BPF_KPROBE(ig_fssl_statfs_e, struct dentry *dentry, struct kstatfs *buf)
185
{
186
	return probe_entry(dentry, F_STATFS, 0, 0);
187
}
188

189
SEC("kretprobe/dummy_file_statfs")
190
int BPF_KRETPROBE(ig_fssl_statfs_x)
191
{
192
	return probe_exit(ctx, F_STATFS, 0);
193
}
194

195
// Comment out the fentry/fexit functions as we don't support them yet.
196
//SEC("fentry/dummy_file_read")
197
//int BPF_PROG(file_read_fentry, struct kiocb *iocb)
198
//{
199
//	struct file *fp = iocb->ki_filp;
200
//	loff_t start = iocb->ki_pos;
201
//
202
//	return probe_entry(fp, start, 0);
203
//}
204
//
205
//SEC("fexit/dummy_file_read")
206
//int BPF_PROG(file_read_fexit, struct kiocb *iocb, struct iov_iter *to, ssize_t ret)
207
//{
208
//	return probe_exit(ctx, READ, ret);
209
//}
210
//
211
//SEC("fentry/dummy_file_write")
212
//int BPF_PROG(file_write_fentry, struct kiocb *iocb)
213
//{
214
//	struct file *fp = iocb->ki_filp;
215
//	loff_t start = iocb->ki_pos;
216
//
217
//	return probe_entry(fp, start, 0);
218
//}
219
//
220
//SEC("fexit/dummy_file_write")
221
//int BPF_PROG(file_write_fexit, struct kiocb *iocb, struct iov_iter *from, ssize_t ret)
222
//{
223
//	return probe_exit(ctx, WRITE, ret);
224
//}
225
//
226
//SEC("fentry/dummy_file_open")
227
//int BPF_PROG(file_open_fentry, struct inode *inode, struct file *file)
228
//{
229
//	return probe_entry(file, 0, 0);
230
//}
231
//
232
//SEC("fexit/dummy_file_open")
233
//int BPF_PROG(file_open_fexit)
234
//{
235
//	return probe_exit(ctx, OPEN, 0);
236
//}
237
//
238
//SEC("fentry/dummy_file_sync")
239
//int BPF_PROG(file_sync_fentry, struct file *file, loff_t start, loff_t end)
240
//{
241
//	return probe_entry(file, start, end);
242
//}
243
//
244
//SEC("fexit/dummy_file_sync")
245
//int BPF_PROG(file_sync_fexit)
246
//{
247
//	return probe_exit(ctx, FSYNC, 0);
248
//}
249

250
char LICENSE[] SEC("license") = "GPL";
251

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.