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 7extern struct kmem_cache *fanotify_mark_cache; 8extern struct kmem_cache *fanotify_fid_event_cachep; 9extern struct kmem_cache *fanotify_path_event_cachep; 10extern struct kmem_cache *fanotify_perm_event_cachep; 11 12/* Possible states of the permission event */ 13enum { 14 FAN_EVENT_INIT, 15 FAN_EVENT_REPORTED, 16 FAN_EVENT_ANSWERED, 17 FAN_EVENT_CANCELED, 18}; 19 20/* 21 * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation). 22 * fh buf should be dword aligned. On 64bit arch, the ext_buf pointer is 23 * stored in either the first or last 2 dwords. 24 */ 25#define FANOTIFY_INLINE_FH_LEN (3 << 2) 26#define FANOTIFY_FH_HDR_LEN offsetof(struct fanotify_fh, buf) 27 28/* Fixed size struct for file handle */ 29struct fanotify_fh { 30 u8 type; 31 u8 len; 32#define FANOTIFY_FH_FLAG_EXT_BUF 1 33 u8 flags; 34 u8 pad; 35 unsigned char buf[]; 36} __aligned(4); 37 38/* Variable size struct for dir file handle + child file handle + name */ 39struct fanotify_info { 40 /* size of dir_fh/file_fh including fanotify_fh hdr size */ 41 u8 dir_fh_totlen; 42 u8 file_fh_totlen; 43 u8 name_len; 44 u8 pad; 45 unsigned char buf[]; 46 /* 47 * (struct fanotify_fh) dir_fh starts at buf[0] 48 * (optional) file_fh starts at buf[dir_fh_totlen] 49 * name starts at buf[dir_fh_totlen + file_fh_totlen] 50 */ 51} __aligned(4); 52 53static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) 54{ 55 return (fh->flags & FANOTIFY_FH_FLAG_EXT_BUF); 56} 57 58static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh) 59{ 60 BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN % 4); 61 BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) > 62 FANOTIFY_INLINE_FH_LEN); 63 return (char **)ALIGN((unsigned long)(fh->buf), __alignof__(char *)); 64} 65 66static inline void *fanotify_fh_ext_buf(struct fanotify_fh *fh) 67{ 68 return *fanotify_fh_ext_buf_ptr(fh); 69} 70 71static inline void *fanotify_fh_buf(struct fanotify_fh *fh) 72{ 73 return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh->buf; 74} 75 76static inline int fanotify_info_dir_fh_len(struct fanotify_info *info) 77{ 78 if (!info->dir_fh_totlen || 79 WARN_ON_ONCE(info->dir_fh_totlen < FANOTIFY_FH_HDR_LEN)) 80 return 0; 81 82 return info->dir_fh_totlen - FANOTIFY_FH_HDR_LEN; 83} 84 85static inline struct fanotify_fh *fanotify_info_dir_fh(struct fanotify_info *info) 86{ 87 BUILD_BUG_ON(offsetof(struct fanotify_info, buf) % 4); 88 89 return (struct fanotify_fh *)info->buf; 90} 91 92static inline int fanotify_info_file_fh_len(struct fanotify_info *info) 93{ 94 if (!info->file_fh_totlen || 95 WARN_ON_ONCE(info->file_fh_totlen < FANOTIFY_FH_HDR_LEN)) 96 return 0; 97 98 return info->file_fh_totlen - FANOTIFY_FH_HDR_LEN; 99} 100 101static inline struct fanotify_fh *fanotify_info_file_fh(struct fanotify_info *info) 102{ 103 return (struct fanotify_fh *)(info->buf + info->dir_fh_totlen); 104} 105 106static inline const char *fanotify_info_name(struct fanotify_info *info) 107{ 108 return info->buf + info->dir_fh_totlen + info->file_fh_totlen; 109} 110 111static inline void fanotify_info_init(struct fanotify_info *info) 112{ 113 info->dir_fh_totlen = 0; 114 info->file_fh_totlen = 0; 115 info->name_len = 0; 116} 117 118static inline void fanotify_info_copy_name(struct fanotify_info *info, 119 const struct qstr *name) 120{ 121 info->name_len = name->len; 122 strcpy(info->buf + info->dir_fh_totlen + info->file_fh_totlen, 123 name->name); 124} 125 126/* 127 * Common structure for fanotify events. Concrete structs are allocated in 128 * fanotify_handle_event() and freed when the information is retrieved by 129 * userspace. The type of event determines how it was allocated, how it will 130 * be freed and which concrete struct it may be cast to. 131 */ 132enum fanotify_event_type { 133 FANOTIFY_EVENT_TYPE_FID, /* fixed length */ 134 FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */ 135 FANOTIFY_EVENT_TYPE_PATH, 136 FANOTIFY_EVENT_TYPE_PATH_PERM, 137 FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */ 138}; 139 140struct fanotify_event { 141 struct fsnotify_event fse; 142 u32 mask; 143 enum fanotify_event_type type; 144 struct pid *pid; 145}; 146 147static inline void fanotify_init_event(struct fanotify_event *event, 148 unsigned long id, u32 mask) 149{ 150 fsnotify_init_event(&event->fse, id); 151 event->mask = mask; 152 event->pid = NULL; 153} 154 155struct fanotify_fid_event { 156 struct fanotify_event fae; 157 __kernel_fsid_t fsid; 158 struct fanotify_fh object_fh; 159 /* Reserve space in object_fh.buf[] - access with fanotify_fh_buf() */ 160 unsigned char _inline_fh_buf[FANOTIFY_INLINE_FH_LEN]; 161}; 162 163static inline struct fanotify_fid_event * 164FANOTIFY_FE(struct fanotify_event *event) 165{ 166 return container_of(event, struct fanotify_fid_event, fae); 167} 168 169struct fanotify_name_event { 170 struct fanotify_event fae; 171 __kernel_fsid_t fsid; 172 struct fanotify_info info; 173}; 174 175static inline struct fanotify_name_event * 176FANOTIFY_NE(struct fanotify_event *event) 177{ 178 return container_of(event, struct fanotify_name_event, fae); 179} 180 181static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event) 182{ 183 if (event->type == FANOTIFY_EVENT_TYPE_FID) 184 return &FANOTIFY_FE(event)->fsid; 185 else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 186 return &FANOTIFY_NE(event)->fsid; 187 else 188 return NULL; 189} 190 191static inline struct fanotify_fh *fanotify_event_object_fh( 192 struct fanotify_event *event) 193{ 194 if (event->type == FANOTIFY_EVENT_TYPE_FID) 195 return &FANOTIFY_FE(event)->object_fh; 196 else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 197 return fanotify_info_file_fh(&FANOTIFY_NE(event)->info); 198 else 199 return NULL; 200} 201 202static inline struct fanotify_info *fanotify_event_info( 203 struct fanotify_event *event) 204{ 205 if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 206 return &FANOTIFY_NE(event)->info; 207 else 208 return NULL; 209} 210 211static inline int fanotify_event_object_fh_len(struct fanotify_event *event) 212{ 213 struct fanotify_info *info = fanotify_event_info(event); 214 struct fanotify_fh *fh = fanotify_event_object_fh(event); 215 216 if (info) 217 return info->file_fh_totlen ? fh->len : 0; 218 else 219 return fh ? fh->len : 0; 220} 221 222static inline int fanotify_event_dir_fh_len(struct fanotify_event *event) 223{ 224 struct fanotify_info *info = fanotify_event_info(event); 225 226 return info ? fanotify_info_dir_fh_len(info) : 0; 227} 228 229struct fanotify_path_event { 230 struct fanotify_event fae; 231 struct path path; 232}; 233 234static inline struct fanotify_path_event * 235FANOTIFY_PE(struct fanotify_event *event) 236{ 237 return container_of(event, struct fanotify_path_event, fae); 238} 239 240/* 241 * Structure for permission fanotify events. It gets allocated and freed in 242 * fanotify_handle_event() since we wait there for user response. When the 243 * information is retrieved by userspace the structure is moved from 244 * group->notification_list to group->fanotify_data.access_list to wait for 245 * user response. 246 */ 247struct fanotify_perm_event { 248 struct fanotify_event fae; 249 struct path path; 250 unsigned short response; /* userspace answer to the event */ 251 unsigned short state; /* state of the event */ 252 int fd; /* fd we passed to userspace for this event */ 253}; 254 255static inline struct fanotify_perm_event * 256FANOTIFY_PERM(struct fanotify_event *event) 257{ 258 return container_of(event, struct fanotify_perm_event, fae); 259} 260 261static inline bool fanotify_is_perm_event(u32 mask) 262{ 263 return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) && 264 mask & FANOTIFY_PERM_EVENTS; 265} 266 267static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) 268{ 269 return container_of(fse, struct fanotify_event, fse); 270} 271 272static inline bool fanotify_event_has_path(struct fanotify_event *event) 273{ 274 return event->type == FANOTIFY_EVENT_TYPE_PATH || 275 event->type == FANOTIFY_EVENT_TYPE_PATH_PERM; 276} 277 278static inline struct path *fanotify_event_path(struct fanotify_event *event) 279{ 280 if (event->type == FANOTIFY_EVENT_TYPE_PATH) 281 return &FANOTIFY_PE(event)->path; 282 else if (event->type == FANOTIFY_EVENT_TYPE_PATH_PERM) 283 return &FANOTIFY_PERM(event)->path; 284 else 285 return NULL; 286} 287