Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : #include <linux/fsnotify_backend.h> 3 : : #include <linux/path.h> 4 : : #include <linux/slab.h> 5 : : #include <linux/exportfs.h> 6 : : 7 : : extern struct kmem_cache *fanotify_mark_cache; 8 : : extern struct kmem_cache *fanotify_event_cachep; 9 : : extern struct kmem_cache *fanotify_perm_event_cachep; 10 : : 11 : : /* Possible states of the permission event */ 12 : : enum { 13 : : FAN_EVENT_INIT, 14 : : FAN_EVENT_REPORTED, 15 : : FAN_EVENT_ANSWERED, 16 : : FAN_EVENT_CANCELED, 17 : : }; 18 : : 19 : : /* 20 : : * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation). 21 : : * For 32bit arch, fid increases the size of fanotify_event by 12 bytes and 22 : : * fh_* fields increase the size of fanotify_event by another 4 bytes. 23 : : * For 64bit arch, fid increases the size of fanotify_fid by 8 bytes and 24 : : * fh_* fields are packed in a hole after mask. 25 : : */ 26 : : #if BITS_PER_LONG == 32 27 : : #define FANOTIFY_INLINE_FH_LEN (3 << 2) 28 : : #else 29 : : #define FANOTIFY_INLINE_FH_LEN (4 << 2) 30 : : #endif 31 : : 32 : : struct fanotify_fid { 33 : : __kernel_fsid_t fsid; 34 : : union { 35 : : unsigned char fh[FANOTIFY_INLINE_FH_LEN]; 36 : : unsigned char *ext_fh; 37 : : }; 38 : : }; 39 : : 40 : : static inline void *fanotify_fid_fh(struct fanotify_fid *fid, 41 : : unsigned int fh_len) 42 : : { 43 : 0 : return fh_len <= FANOTIFY_INLINE_FH_LEN ? fid->fh : fid->ext_fh; 44 : : } 45 : : 46 : 0 : static inline bool fanotify_fid_equal(struct fanotify_fid *fid1, 47 : : struct fanotify_fid *fid2, 48 : : unsigned int fh_len) 49 : : { 50 : 0 : return fid1->fsid.val[0] == fid2->fsid.val[0] && 51 : 0 : fid1->fsid.val[1] == fid2->fsid.val[1] && 52 : 0 : !memcmp(fanotify_fid_fh(fid1, fh_len), 53 : : fanotify_fid_fh(fid2, fh_len), fh_len); 54 : : } 55 : : 56 : : /* 57 : : * Structure for normal fanotify events. It gets allocated in 58 : : * fanotify_handle_event() and freed when the information is retrieved by 59 : : * userspace 60 : : */ 61 : : struct fanotify_event { 62 : : struct fsnotify_event fse; 63 : : u32 mask; 64 : : /* 65 : : * Those fields are outside fanotify_fid to pack fanotify_event nicely 66 : : * on 64bit arch and to use fh_type as an indication of whether path 67 : : * or fid are used in the union: 68 : : * FILEID_ROOT (0) for path, > 0 for fid, FILEID_INVALID for neither. 69 : : */ 70 : : u8 fh_type; 71 : : u8 fh_len; 72 : : u16 pad; 73 : : union { 74 : : /* 75 : : * We hold ref to this path so it may be dereferenced at any 76 : : * point during this object's lifetime 77 : : */ 78 : : struct path path; 79 : : /* 80 : : * With FAN_REPORT_FID, we do not hold any reference on the 81 : : * victim object. Instead we store its NFS file handle and its 82 : : * filesystem's fsid as a unique identifier. 83 : : */ 84 : : struct fanotify_fid fid; 85 : : }; 86 : : struct pid *pid; 87 : : }; 88 : : 89 : : static inline bool fanotify_event_has_path(struct fanotify_event *event) 90 : : { 91 : 0 : return event->fh_type == FILEID_ROOT; 92 : : } 93 : : 94 : : static inline bool fanotify_event_has_fid(struct fanotify_event *event) 95 : : { 96 : 0 : return event->fh_type != FILEID_ROOT && 97 : : event->fh_type != FILEID_INVALID; 98 : : } 99 : : 100 : : static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event) 101 : : { 102 : 0 : return fanotify_event_has_fid(event) && 103 : 0 : event->fh_len > FANOTIFY_INLINE_FH_LEN; 104 : : } 105 : : 106 : : static inline void *fanotify_event_fh(struct fanotify_event *event) 107 : : { 108 : 0 : return fanotify_fid_fh(&event->fid, event->fh_len); 109 : : } 110 : : 111 : : /* 112 : : * Structure for permission fanotify events. It gets allocated and freed in 113 : : * fanotify_handle_event() since we wait there for user response. When the 114 : : * information is retrieved by userspace the structure is moved from 115 : : * group->notification_list to group->fanotify_data.access_list to wait for 116 : : * user response. 117 : : */ 118 : : struct fanotify_perm_event { 119 : : struct fanotify_event fae; 120 : : unsigned short response; /* userspace answer to the event */ 121 : : unsigned short state; /* state of the event */ 122 : : int fd; /* fd we passed to userspace for this event */ 123 : : }; 124 : : 125 : : static inline struct fanotify_perm_event * 126 : : FANOTIFY_PE(struct fsnotify_event *fse) 127 : : { 128 : : return container_of(fse, struct fanotify_perm_event, fae.fse); 129 : : } 130 : : 131 : : static inline bool fanotify_is_perm_event(u32 mask) 132 : : { 133 : : return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) && 134 : : mask & FANOTIFY_PERM_EVENTS; 135 : : } 136 : : 137 : : static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) 138 : : { 139 : : return container_of(fse, struct fanotify_event, fse); 140 : : } 141 : : 142 : : struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, 143 : : struct inode *inode, u32 mask, 144 : : const void *data, int data_type, 145 : : __kernel_fsid_t *fsid);