Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : #include <linux/fs.h> 3 : : #include <linux/bpf-cgroup.h> 4 : : 5 : : #define DEVCG_ACC_MKNOD 1 6 : : #define DEVCG_ACC_READ 2 7 : : #define DEVCG_ACC_WRITE 4 8 : : #define DEVCG_ACC_MASK (DEVCG_ACC_MKNOD | DEVCG_ACC_READ | DEVCG_ACC_WRITE) 9 : : 10 : : #define DEVCG_DEV_BLOCK 1 11 : : #define DEVCG_DEV_CHAR 2 12 : : #define DEVCG_DEV_ALL 4 /* this represents all devices */ 13 : : 14 : : #ifdef CONFIG_CGROUP_DEVICE 15 : : extern int __devcgroup_check_permission(short type, u32 major, u32 minor, 16 : : short access); 17 : : #else 18 : : static inline int __devcgroup_check_permission(short type, u32 major, u32 minor, 19 : : short access) 20 : : { return 0; } 21 : : #endif 22 : : 23 : : #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF) 24 : 3 : static inline int devcgroup_check_permission(short type, u32 major, u32 minor, 25 : : short access) 26 : : { 27 : 3 : int rc = BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type, major, minor, access); 28 : : 29 : 3 : if (rc) 30 : : return -EPERM; 31 : : 32 : 3 : return __devcgroup_check_permission(type, major, minor, access); 33 : : } 34 : : 35 : 3 : static inline int devcgroup_inode_permission(struct inode *inode, int mask) 36 : : { 37 : : short type, access = 0; 38 : : 39 : 3 : if (likely(!inode->i_rdev)) 40 : : return 0; 41 : : 42 : 3 : if (S_ISBLK(inode->i_mode)) 43 : : type = DEVCG_DEV_BLOCK; 44 : 3 : else if (S_ISCHR(inode->i_mode)) 45 : : type = DEVCG_DEV_CHAR; 46 : : else 47 : : return 0; 48 : : 49 : 3 : if (mask & MAY_WRITE) 50 : : access |= DEVCG_ACC_WRITE; 51 : 3 : if (mask & MAY_READ) 52 : 3 : access |= DEVCG_ACC_READ; 53 : : 54 : 3 : return devcgroup_check_permission(type, imajor(inode), iminor(inode), 55 : : access); 56 : : } 57 : : 58 : 3 : static inline int devcgroup_inode_mknod(int mode, dev_t dev) 59 : : { 60 : : short type; 61 : : 62 : 3 : if (!S_ISBLK(mode) && !S_ISCHR(mode)) 63 : : return 0; 64 : : 65 : 3 : if (S_ISBLK(mode)) 66 : : type = DEVCG_DEV_BLOCK; 67 : : else 68 : : type = DEVCG_DEV_CHAR; 69 : : 70 : 3 : return devcgroup_check_permission(type, MAJOR(dev), MINOR(dev), 71 : : DEVCG_ACC_MKNOD); 72 : : } 73 : : 74 : : #else 75 : : static inline int devcgroup_inode_permission(struct inode *inode, int mask) 76 : : { return 0; } 77 : : static inline int devcgroup_inode_mknod(int mode, dev_t dev) 78 : : { return 0; } 79 : : #endif