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