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