• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * fuse_media eBPF program
3  *
4  * Copyright (C) 2021 Google
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version
8  * 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #include <bpf_helpers.h>
18 
19 #include <stdint.h>
20 
21 #define __KERNEL__
22 #include <fuse_kernel.h>
23 
24 #define bpf_printk(fmt, ...)                                       \
25     ({                                                             \
26         char ____fmt[] = fmt;                                      \
27         bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
28     })
29 
30 DEFINE_BPF_PROG("fuse/media", AID_ROOT, AID_MEDIA_RW, fuse_media)
31 (struct fuse_args* fa) {
32     switch (fa->opcode) {
33         case FUSE_LOOKUP | FUSE_PREFILTER: {
34             const char* name = fa->in_args[0].value;
35 
36             bpf_printk("LOOKUP: %lx %s", fa->nodeid, name);
37             if (fa->nodeid == 1)
38                 return FUSE_BPF_USER_FILTER | FUSE_BPF_BACKING;
39             else
40                 return FUSE_BPF_BACKING;
41         }
42 
43             /* FUSE_FORGET */
44 
45         case FUSE_GETATTR | FUSE_PREFILTER: {
46             const struct fuse_getattr_in* fgi = fa->in_args[0].value;
47 
48             bpf_printk("GETATTR: %d", fgi->fh);
49             return FUSE_BPF_BACKING;
50         }
51 
52         case FUSE_SETATTR | FUSE_PREFILTER: {
53             const struct fuse_setattr_in* fsi = fa->in_args[0].value;
54 
55             bpf_printk("SETATTR: %d", fsi->fh);
56             return FUSE_BPF_BACKING;
57         }
58 
59             /* FUSE_READLINK */
60             /* FUSE_SYMLINK */
61 
62         case FUSE_MKNOD | FUSE_PREFILTER: {
63             const struct fuse_mknod_in* fmi = fa->in_args[0].value;
64             const char* name = fa->in_args[1].value;
65 
66             bpf_printk("MKNOD: %s %x %x", name, fmi->rdev | fmi->mode, fmi->umask);
67             return FUSE_BPF_BACKING;
68         }
69 
70         case FUSE_MKDIR | FUSE_PREFILTER: {
71             const struct fuse_mkdir_in* fmi = fa->in_args[0].value;
72             const char* name = fa->in_args[1].value;
73 
74             bpf_printk("MKDIR: %s %x %x", name, fmi->mode, fmi->umask);
75             return FUSE_BPF_BACKING;
76         }
77 
78         case FUSE_UNLINK | FUSE_PREFILTER: {
79             const char* name = fa->in_args[0].value;
80 
81             bpf_printk("UNLINK: %s", name);
82             return FUSE_BPF_BACKING;
83         }
84 
85         case FUSE_RMDIR | FUSE_PREFILTER: {
86             const char* name = fa->in_args[0].value;
87 
88             bpf_printk("RMDIR: %s", name);
89             return FUSE_BPF_BACKING;
90         }
91 
92         case FUSE_RENAME | FUSE_PREFILTER: {
93             const char* name_old = fa->in_args[1].value;
94             const char* name_new = fa->in_args[2].value;
95 
96             bpf_printk("RENAME: %s to %s", name_old, name_new);
97             return FUSE_BPF_BACKING;
98         }
99 
100         case FUSE_LINK | FUSE_PREFILTER: {
101             const struct fuse_link_in* fli = fa->in_args[0].value;
102             const char* dst_name = fa->in_args[1].value;
103 
104             bpf_printk("LINK: %d %s", fli->oldnodeid, dst_name);
105             return FUSE_BPF_BACKING;
106         }
107 
108         case FUSE_OPEN | FUSE_PREFILTER: {
109             bpf_printk("OPEN: %d", fa->nodeid);
110             return FUSE_BPF_BACKING;
111         }
112 
113         case FUSE_READ | FUSE_PREFILTER: {
114             const struct fuse_read_in* fri = fa->in_args[0].value;
115 
116             bpf_printk("READ: fh: %lu, offset %lu, size %lu", fri->fh, fri->offset, fri->size);
117             return FUSE_BPF_BACKING;
118         }
119 
120         case FUSE_WRITE | FUSE_PREFILTER: {
121             const struct fuse_write_in* fwi = fa->in_args[0].value;
122 
123             bpf_printk("WRITE: fh: %lu, offset %lu, size %lu", fwi->fh, fwi->offset, fwi->size);
124             return FUSE_BPF_BACKING;
125         }
126 
127             /* FUSE_STATFS */
128 
129         case FUSE_RELEASE | FUSE_PREFILTER: {
130             const struct fuse_release_in* fri = fa->in_args[0].value;
131 
132             bpf_printk("RELEASE: %d", fri->fh);
133             return FUSE_BPF_BACKING;
134         }
135 
136             /* FUSE_FSYNC */
137 
138         case FUSE_SETXATTR | FUSE_PREFILTER: {
139             const char* name = fa->in_args[1].value;
140 
141             bpf_printk("SETXATTR: %d %s", fa->nodeid, name);
142             return FUSE_BPF_BACKING;
143         }
144 
145         case FUSE_GETXATTR | FUSE_PREFILTER: {
146             const char* name = fa->in_args[1].value;
147 
148             bpf_printk("GETXATTR: %d %s", fa->nodeid, name);
149             return FUSE_BPF_BACKING;
150         }
151 
152         case FUSE_LISTXATTR | FUSE_PREFILTER: {
153             const char* name = fa->in_args[1].value;
154 
155             bpf_printk("LISTXATTR: %d %s", fa->nodeid, name);
156             return FUSE_BPF_BACKING;
157         }
158 
159             /* FUSE_REMOVEXATTR */
160 
161         case FUSE_FLUSH | FUSE_PREFILTER: {
162             const struct fuse_flush_in* ffi = fa->in_args[0].value;
163 
164             bpf_printk("FLUSH: %d", ffi->fh);
165             return FUSE_BPF_BACKING;
166         }
167 
168             /* FUSE_INIT */
169 
170         case FUSE_OPENDIR | FUSE_PREFILTER: {
171             bpf_printk("OPENDIR: %d", fa->nodeid);
172             return FUSE_BPF_BACKING;
173         }
174 
175         case FUSE_READDIR | FUSE_PREFILTER: {
176             const struct fuse_read_in* fri = fa->in_args[0].value;
177             bpf_printk("READDIR: fh: %lu", fri->fh, fri->offset);
178             return FUSE_BPF_BACKING;
179         }
180 
181         case FUSE_RELEASEDIR | FUSE_PREFILTER: {
182             const struct fuse_release_in* fri = fa->in_args[0].value;
183 
184             bpf_printk("RELEASEDIR: %d", fri->fh);
185             return FUSE_BPF_BACKING;
186         }
187 
188             /* FUSE_FSYNCDIR */
189             /* FUSE_GETLK */
190             /* FUSE_SETLK */
191             /* FUSE_SETLKW */
192 
193         case FUSE_ACCESS | FUSE_PREFILTER: {
194             bpf_printk("ACCESS: %d", fa->nodeid);
195             return FUSE_BPF_BACKING;
196         }
197 
198         case FUSE_CREATE | FUSE_PREFILTER: {
199             bpf_printk("CREATE: %s", fa->in_args[1].value);
200             return FUSE_BPF_BACKING;
201         }
202 
203             /* FUSE_INTERRUPT */
204             /* FUSE_BMAP */
205             /* FUSE_DESTROY */
206             /* FUSE_IOCTL */
207             /* FUSE_POLL */
208             /* FUSE_NOTIFY_REPLY */
209             /* FUSE_BATCH_FORGET */
210 
211         case FUSE_FALLOCATE | FUSE_PREFILTER: {
212             const struct fuse_fallocate_in* ffa = fa->in_args[0].value;
213 
214             bpf_printk("FALLOCATE: %d %lu", ffa->fh, ffa->length);
215             return FUSE_BPF_BACKING;
216         }
217 
218             /* FUSE_READDIRPLUS */
219             /* FUSE_RENAME2 */
220             /* FUSE_LSEEK */
221             /* FUSE_COPY_FILE_RANGE */
222             /* CUSE_INIT */
223 
224         case FUSE_CANONICAL_PATH | FUSE_PREFILTER: {
225             bpf_printk("CANONICAL_PATH: %d", fa->nodeid);
226             return FUSE_BPF_BACKING;
227         }
228 
229         default:
230             if (fa->opcode & FUSE_PREFILTER)
231                 bpf_printk("Prefilter *** UNKNOWN *** opcode: %d", fa->opcode & FUSE_OPCODE_FILTER);
232             else if (fa->opcode & FUSE_POSTFILTER)
233                 bpf_printk("Postfilter *** UNKNOWN *** opcode: %d",
234                            fa->opcode & FUSE_OPCODE_FILTER);
235             else
236                 bpf_printk("*** UNKNOWN *** opcode: %d", fa->opcode);
237             return FUSE_BPF_BACKING;
238     }
239 }
240 
241 LICENSE("GPL");
242