1 /* 2 * fuseMedia 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_bpf_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_PREFILTER: %lx %s", fa->nodeid, name); 37 return FUSE_BPF_BACKING | FUSE_BPF_POST_FILTER; 38 } 39 40 case FUSE_LOOKUP | FUSE_POSTFILTER: { 41 struct fuse_entry_out* feo = fa->out_args[0].value; 42 struct fuse_entry_bpf_out* febo = fa->out_args[1].value; 43 uint64_t uid_gid = bpf_get_current_uid_gid(); 44 uint32_t uid = uid_gid; 45 uint32_t gid = uid_gid >> 32; 46 47 febo->bpf_action = FUSE_ACTION_REMOVE; 48 49 /* If the decision is easy, make it here for performance */ 50 if (fa->error_in || (feo->attr.mode & 0001) || 51 ((feo->attr.mode & 0010) && gid == feo->attr.gid) || 52 ((feo->attr.mode & 0100) && uid == feo->attr.uid)) 53 return 0; 54 55 /* Delegate to the daemon */ 56 return FUSE_BPF_USER_FILTER; 57 } 58 59 case FUSE_READDIR | FUSE_PREFILTER: { 60 return FUSE_BPF_BACKING | FUSE_BPF_POST_FILTER; 61 } 62 63 case FUSE_READDIR | FUSE_POSTFILTER: { 64 return FUSE_BPF_USER_FILTER; 65 } 66 67 default: 68 return FUSE_BPF_BACKING; 69 } 70 } 71 72 LICENSE("GPL"); 73