1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 // Copyright (c) 2021 Google LLC
3
4 #define __EXPORTED_HEADERS__
5 #define __KERNEL__
6
7 #ifdef __ANDROID__
8 #include <stdint.h>
9 #endif
10
11 #include <uapi/linux/types.h>
12 #include <uapi/linux/bpf.h>
13 #include <uapi/linux/fuse.h>
14 #include <uapi/linux/errno.h>
15
16 struct fuse_bpf_map {
17 int map_type;
18 size_t key_size;
19 size_t value_size;
20 int max_entries;
21 };
22
23 static void *(*bpf_map_lookup_elem)(struct fuse_bpf_map *map, void *key)
24 = (void *) 1;
25
26 static void *(*bpf_map_update_elem)(struct fuse_bpf_map *map, void *key,
27 void *value, int flags)
28 = (void *) 2;
29
30 static long (*bpf_trace_printk)(const char *fmt, __u32 fmt_size, ...)
31 = (void *) 6;
32
33 static long (*bpf_get_current_pid_tgid)()
34 = (void *) 14;
35
36 static long (*bpf_get_current_uid_gid)()
37 = (void *) 15;
38
39 #define bpf_printk(fmt, ...) \
40 ({ \
41 char ____fmt[] = fmt; \
42 bpf_trace_printk(____fmt, sizeof(____fmt), \
43 ##__VA_ARGS__); \
44 })
45
46 #define SEC(NAME) __attribute__((section(NAME), used))
47
48 SEC("dummy")
49
strcmp(const char * a,const char * b)50 inline int strcmp(const char *a, const char *b)
51 {
52 int i;
53
54 for (i = 0; i < __builtin_strlen(b) + 1; ++i)
55 if (a[i] != b[i])
56 return -1;
57
58 return 0;
59 }
60
61 SEC("maps") struct fuse_bpf_map test_map = {
62 BPF_MAP_TYPE_ARRAY,
63 sizeof(uint32_t),
64 sizeof(uint32_t),
65 1000,
66 };
67
68 SEC("maps") struct fuse_bpf_map test_map2 = {
69 BPF_MAP_TYPE_HASH,
70 sizeof(uint32_t),
71 sizeof(uint64_t),
72 76,
73 };
74
75 SEC("test_daemon")
76
trace_daemon(struct fuse_bpf_args * fa)77 int trace_daemon(struct fuse_bpf_args *fa)
78 {
79 uint64_t uid_gid = bpf_get_current_uid_gid();
80 uint32_t uid = uid_gid & 0xffffffff;
81 uint64_t pid_tgid = bpf_get_current_pid_tgid();
82 uint32_t pid = pid_tgid & 0xffffffff;
83 uint32_t key = 23;
84 uint32_t *pvalue;
85
86
87 pvalue = bpf_map_lookup_elem(&test_map, &key);
88 if (pvalue) {
89 uint32_t value = *pvalue;
90
91 bpf_printk("pid %u uid %u value %u", pid, uid, value);
92 value++;
93 bpf_map_update_elem(&test_map, &key, &value, BPF_ANY);
94 }
95
96 switch (fa->opcode) {
97 case FUSE_ACCESS | FUSE_PREFILTER: {
98 bpf_printk("Access: %d", fa->nodeid);
99 return FUSE_BPF_BACKING;
100 }
101
102 case FUSE_GETATTR | FUSE_PREFILTER: {
103 const struct fuse_getattr_in *fgi = fa->in_args[0].value;
104
105 bpf_printk("Get Attr %d", fgi->fh);
106 return FUSE_BPF_BACKING;
107 }
108
109 case FUSE_SETATTR | FUSE_PREFILTER: {
110 const struct fuse_setattr_in *fsi = fa->in_args[0].value;
111
112 bpf_printk("Set Attr %d", fsi->fh);
113 return FUSE_BPF_BACKING;
114 }
115
116 case FUSE_OPENDIR | FUSE_PREFILTER: {
117 bpf_printk("Open Dir: %d", fa->nodeid);
118 return FUSE_BPF_BACKING;
119 }
120
121 case FUSE_READDIR | FUSE_PREFILTER: {
122 const struct fuse_read_in *fri = fa->in_args[0].value;
123
124 bpf_printk("Read Dir: fh: %lu", fri->fh, fri->offset);
125 return FUSE_BPF_BACKING;
126 }
127
128 case FUSE_LOOKUP | FUSE_PREFILTER: {
129 const char *name = fa->in_args[0].value;
130
131 bpf_printk("Lookup: %lx %s", fa->nodeid, name);
132 if (fa->nodeid == 1)
133 return FUSE_BPF_USER_FILTER | FUSE_BPF_BACKING;
134 else
135 return FUSE_BPF_BACKING;
136 }
137
138 case FUSE_MKNOD | FUSE_PREFILTER: {
139 const struct fuse_mknod_in *fmi = fa->in_args[0].value;
140 const char *name = fa->in_args[1].value;
141
142 bpf_printk("mknod %s %x %x", name, fmi->rdev | fmi->mode, fmi->umask);
143 return FUSE_BPF_BACKING;
144 }
145
146 case FUSE_MKDIR | FUSE_PREFILTER: {
147 const struct fuse_mkdir_in *fmi = fa->in_args[0].value;
148 const char *name = fa->in_args[1].value;
149
150 bpf_printk("mkdir: %s %x %x", name, fmi->mode, fmi->umask);
151 return FUSE_BPF_BACKING;
152 }
153
154 case FUSE_RMDIR | FUSE_PREFILTER: {
155 const char *name = fa->in_args[0].value;
156
157 bpf_printk("rmdir: %s", name);
158 return FUSE_BPF_BACKING;
159 }
160
161 case FUSE_RENAME | FUSE_PREFILTER: {
162 const char *oldname = fa->in_args[1].value;
163 const char *newname = fa->in_args[2].value;
164
165 bpf_printk("rename from %s", oldname);
166 bpf_printk("rename to %s", newname);
167 return FUSE_BPF_BACKING;
168 }
169
170 case FUSE_RENAME2 | FUSE_PREFILTER: {
171 const struct fuse_rename2_in *fri = fa->in_args[0].value;
172 uint32_t flags = fri->flags;
173 const char *oldname = fa->in_args[1].value;
174 const char *newname = fa->in_args[2].value;
175
176 bpf_printk("rename(%x) from %s", flags, oldname);
177 bpf_printk("rename to %s", newname);
178 return FUSE_BPF_BACKING;
179 }
180
181 case FUSE_UNLINK | FUSE_PREFILTER: {
182 const char *name = fa->in_args[0].value;
183
184 bpf_printk("unlink: %s", name);
185 return FUSE_BPF_BACKING;
186 }
187
188 case FUSE_LINK | FUSE_PREFILTER: {
189 const struct fuse_link_in *fli = fa->in_args[0].value;
190 const char *dst_name = fa->in_args[1].value;
191
192 bpf_printk("Link: %d %s", fli->oldnodeid, dst_name);
193 return FUSE_BPF_BACKING;
194 }
195
196 case FUSE_SYMLINK | FUSE_PREFILTER: {
197 const char *link_name = fa->in_args[0].value;
198 const char *link_dest = fa->in_args[1].value;
199
200 bpf_printk("symlink from %s", link_name);
201 bpf_printk("symlink to %s", link_dest);
202 return FUSE_BPF_BACKING;
203 }
204
205 case FUSE_READLINK | FUSE_PREFILTER: {
206 const char *link_name = fa->in_args[0].value;
207
208 bpf_printk("readlink from %s", link_name);
209 return FUSE_BPF_BACKING;
210 }
211
212 case FUSE_RELEASE | FUSE_PREFILTER: {
213 const struct fuse_release_in *fri = fa->in_args[0].value;
214
215 bpf_printk("Release: %d", fri->fh);
216 return FUSE_BPF_BACKING;
217 }
218
219 case FUSE_RELEASEDIR | FUSE_PREFILTER: {
220 const struct fuse_release_in *fri = fa->in_args[0].value;
221
222 bpf_printk("Release Dir: %d", fri->fh);
223 return FUSE_BPF_BACKING;
224 }
225
226 case FUSE_CREATE | FUSE_PREFILTER: {
227 bpf_printk("Create %s", fa->in_args[1].value);
228 return FUSE_BPF_BACKING;
229 }
230
231 case FUSE_OPEN | FUSE_PREFILTER: {
232 bpf_printk("Open: %d", fa->nodeid);
233 return FUSE_BPF_BACKING;
234 }
235
236 case FUSE_READ | FUSE_PREFILTER: {
237 const struct fuse_read_in *fri = fa->in_args[0].value;
238
239 bpf_printk("Read: fh: %lu, offset %lu, size %lu",
240 fri->fh, fri->offset, fri->size);
241 return FUSE_BPF_BACKING;
242 }
243
244 case FUSE_WRITE | FUSE_PREFILTER: {
245 const struct fuse_write_in *fwi = fa->in_args[0].value;
246
247 bpf_printk("Write: fh: %lu, offset %lu, size %lu",
248 fwi->fh, fwi->offset, fwi->size);
249 return FUSE_BPF_BACKING;
250 }
251
252 case FUSE_FLUSH | FUSE_PREFILTER: {
253 const struct fuse_flush_in *ffi = fa->in_args[0].value;
254
255 bpf_printk("Flush %d", ffi->fh);
256 return FUSE_BPF_BACKING;
257 }
258
259 case FUSE_FALLOCATE | FUSE_PREFILTER: {
260 const struct fuse_fallocate_in *ffa = fa->in_args[0].value;
261
262 bpf_printk("Fallocate %d %lu", ffa->fh, ffa->length);
263 return FUSE_BPF_BACKING;
264 }
265
266 case FUSE_GETXATTR | FUSE_PREFILTER: {
267 const char *name = fa->in_args[1].value;
268
269 bpf_printk("Getxattr %d %s", fa->nodeid, name);
270 return FUSE_BPF_BACKING;
271 }
272
273 case FUSE_LISTXATTR | FUSE_PREFILTER: {
274 const char *name = fa->in_args[1].value;
275
276 bpf_printk("Listxattr %d %s", fa->nodeid, name);
277 return FUSE_BPF_BACKING;
278 }
279
280 case FUSE_SETXATTR | FUSE_PREFILTER: {
281 const char *name = fa->in_args[1].value;
282
283 bpf_printk("Setxattr %d %s", fa->nodeid, name);
284 return FUSE_BPF_BACKING;
285 }
286
287 case FUSE_STATFS | FUSE_PREFILTER: {
288 bpf_printk("statfs %d", fa->nodeid);
289 return FUSE_BPF_BACKING;
290 }
291
292 case FUSE_LSEEK | FUSE_PREFILTER: {
293 const struct fuse_lseek_in *fli = fa->in_args[0].value;
294
295 bpf_printk("lseek type:%d, offset:%lld", fli->whence, fli->offset);
296 return FUSE_BPF_BACKING;
297 }
298
299 default:
300 if (fa->opcode & FUSE_PREFILTER)
301 bpf_printk("prefilter *** UNKNOWN *** opcode: %d",
302 fa->opcode & FUSE_OPCODE_FILTER);
303 else if (fa->opcode & FUSE_POSTFILTER)
304 bpf_printk("postfilter *** UNKNOWN *** opcode: %d",
305 fa->opcode & FUSE_OPCODE_FILTER);
306 else
307 bpf_printk("*** UNKNOWN *** opcode: %d", fa->opcode);
308 return FUSE_BPF_BACKING;
309 }
310 }
311