• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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