fanotify.h (14022B)
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#include <linux/hashtable.h> 7 8extern struct kmem_cache *fanotify_mark_cache; 9extern struct kmem_cache *fanotify_fid_event_cachep; 10extern struct kmem_cache *fanotify_path_event_cachep; 11extern struct kmem_cache *fanotify_perm_event_cachep; 12 13/* Possible states of the permission event */ 14enum { 15 FAN_EVENT_INIT, 16 FAN_EVENT_REPORTED, 17 FAN_EVENT_ANSWERED, 18 FAN_EVENT_CANCELED, 19}; 20 21/* 22 * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation). 23 * fh buf should be dword aligned. On 64bit arch, the ext_buf pointer is 24 * stored in either the first or last 2 dwords. 25 */ 26#define FANOTIFY_INLINE_FH_LEN (3 << 2) 27#define FANOTIFY_FH_HDR_LEN offsetof(struct fanotify_fh, buf) 28 29/* Fixed size struct for file handle */ 30struct fanotify_fh { 31 u8 type; 32 u8 len; 33#define FANOTIFY_FH_FLAG_EXT_BUF 1 34 u8 flags; 35 u8 pad; 36 unsigned char buf[]; 37} __aligned(4); 38 39/* Variable size struct for dir file handle + child file handle + name */ 40struct fanotify_info { 41 /* size of dir_fh/file_fh including fanotify_fh hdr size */ 42 u8 dir_fh_totlen; 43 u8 dir2_fh_totlen; 44 u8 file_fh_totlen; 45 u8 name_len; 46 u8 name2_len; 47 u8 pad[3]; 48 unsigned char buf[]; 49 /* 50 * (struct fanotify_fh) dir_fh starts at buf[0] 51 * (optional) dir2_fh starts at buf[dir_fh_totlen] 52 * (optional) file_fh starts at buf[dir_fh_totlen + dir2_fh_totlen] 53 * name starts at buf[dir_fh_totlen + dir2_fh_totlen + file_fh_totlen] 54 * ... 55 */ 56#define FANOTIFY_DIR_FH_SIZE(info) ((info)->dir_fh_totlen) 57#define FANOTIFY_DIR2_FH_SIZE(info) ((info)->dir2_fh_totlen) 58#define FANOTIFY_FILE_FH_SIZE(info) ((info)->file_fh_totlen) 59#define FANOTIFY_NAME_SIZE(info) ((info)->name_len + 1) 60#define FANOTIFY_NAME2_SIZE(info) ((info)->name2_len + 1) 61 62#define FANOTIFY_DIR_FH_OFFSET(info) 0 63#define FANOTIFY_DIR2_FH_OFFSET(info) \ 64 (FANOTIFY_DIR_FH_OFFSET(info) + FANOTIFY_DIR_FH_SIZE(info)) 65#define FANOTIFY_FILE_FH_OFFSET(info) \ 66 (FANOTIFY_DIR2_FH_OFFSET(info) + FANOTIFY_DIR2_FH_SIZE(info)) 67#define FANOTIFY_NAME_OFFSET(info) \ 68 (FANOTIFY_FILE_FH_OFFSET(info) + FANOTIFY_FILE_FH_SIZE(info)) 69#define FANOTIFY_NAME2_OFFSET(info) \ 70 (FANOTIFY_NAME_OFFSET(info) + FANOTIFY_NAME_SIZE(info)) 71 72#define FANOTIFY_DIR_FH_BUF(info) \ 73 ((info)->buf + FANOTIFY_DIR_FH_OFFSET(info)) 74#define FANOTIFY_DIR2_FH_BUF(info) \ 75 ((info)->buf + FANOTIFY_DIR2_FH_OFFSET(info)) 76#define FANOTIFY_FILE_FH_BUF(info) \ 77 ((info)->buf + FANOTIFY_FILE_FH_OFFSET(info)) 78#define FANOTIFY_NAME_BUF(info) \ 79 ((info)->buf + FANOTIFY_NAME_OFFSET(info)) 80#define FANOTIFY_NAME2_BUF(info) \ 81 ((info)->buf + FANOTIFY_NAME2_OFFSET(info)) 82} __aligned(4); 83 84static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) 85{ 86 return (fh->flags & FANOTIFY_FH_FLAG_EXT_BUF); 87} 88 89static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh) 90{ 91 BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN % 4); 92 BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) > 93 FANOTIFY_INLINE_FH_LEN); 94 return (char **)ALIGN((unsigned long)(fh->buf), __alignof__(char *)); 95} 96 97static inline void *fanotify_fh_ext_buf(struct fanotify_fh *fh) 98{ 99 return *fanotify_fh_ext_buf_ptr(fh); 100} 101 102static inline void *fanotify_fh_buf(struct fanotify_fh *fh) 103{ 104 return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh->buf; 105} 106 107static inline int fanotify_info_dir_fh_len(struct fanotify_info *info) 108{ 109 if (!info->dir_fh_totlen || 110 WARN_ON_ONCE(info->dir_fh_totlen < FANOTIFY_FH_HDR_LEN)) 111 return 0; 112 113 return info->dir_fh_totlen - FANOTIFY_FH_HDR_LEN; 114} 115 116static inline struct fanotify_fh *fanotify_info_dir_fh(struct fanotify_info *info) 117{ 118 BUILD_BUG_ON(offsetof(struct fanotify_info, buf) % 4); 119 120 return (struct fanotify_fh *)FANOTIFY_DIR_FH_BUF(info); 121} 122 123static inline int fanotify_info_dir2_fh_len(struct fanotify_info *info) 124{ 125 if (!info->dir2_fh_totlen || 126 WARN_ON_ONCE(info->dir2_fh_totlen < FANOTIFY_FH_HDR_LEN)) 127 return 0; 128 129 return info->dir2_fh_totlen - FANOTIFY_FH_HDR_LEN; 130} 131 132static inline struct fanotify_fh *fanotify_info_dir2_fh(struct fanotify_info *info) 133{ 134 return (struct fanotify_fh *)FANOTIFY_DIR2_FH_BUF(info); 135} 136 137static inline int fanotify_info_file_fh_len(struct fanotify_info *info) 138{ 139 if (!info->file_fh_totlen || 140 WARN_ON_ONCE(info->file_fh_totlen < FANOTIFY_FH_HDR_LEN)) 141 return 0; 142 143 return info->file_fh_totlen - FANOTIFY_FH_HDR_LEN; 144} 145 146static inline struct fanotify_fh *fanotify_info_file_fh(struct fanotify_info *info) 147{ 148 return (struct fanotify_fh *)FANOTIFY_FILE_FH_BUF(info); 149} 150 151static inline char *fanotify_info_name(struct fanotify_info *info) 152{ 153 if (!info->name_len) 154 return NULL; 155 156 return FANOTIFY_NAME_BUF(info); 157} 158 159static inline char *fanotify_info_name2(struct fanotify_info *info) 160{ 161 if (!info->name2_len) 162 return NULL; 163 164 return FANOTIFY_NAME2_BUF(info); 165} 166 167static inline void fanotify_info_init(struct fanotify_info *info) 168{ 169 BUILD_BUG_ON(FANOTIFY_FH_HDR_LEN + MAX_HANDLE_SZ > U8_MAX); 170 BUILD_BUG_ON(NAME_MAX > U8_MAX); 171 172 info->dir_fh_totlen = 0; 173 info->dir2_fh_totlen = 0; 174 info->file_fh_totlen = 0; 175 info->name_len = 0; 176 info->name2_len = 0; 177} 178 179/* These set/copy helpers MUST be called by order */ 180static inline void fanotify_info_set_dir_fh(struct fanotify_info *info, 181 unsigned int totlen) 182{ 183 if (WARN_ON_ONCE(info->dir2_fh_totlen > 0) || 184 WARN_ON_ONCE(info->file_fh_totlen > 0) || 185 WARN_ON_ONCE(info->name_len > 0) || 186 WARN_ON_ONCE(info->name2_len > 0)) 187 return; 188 189 info->dir_fh_totlen = totlen; 190} 191 192static inline void fanotify_info_set_dir2_fh(struct fanotify_info *info, 193 unsigned int totlen) 194{ 195 if (WARN_ON_ONCE(info->file_fh_totlen > 0) || 196 WARN_ON_ONCE(info->name_len > 0) || 197 WARN_ON_ONCE(info->name2_len > 0)) 198 return; 199 200 info->dir2_fh_totlen = totlen; 201} 202 203static inline void fanotify_info_set_file_fh(struct fanotify_info *info, 204 unsigned int totlen) 205{ 206 if (WARN_ON_ONCE(info->name_len > 0) || 207 WARN_ON_ONCE(info->name2_len > 0)) 208 return; 209 210 info->file_fh_totlen = totlen; 211} 212 213static inline void fanotify_info_copy_name(struct fanotify_info *info, 214 const struct qstr *name) 215{ 216 if (WARN_ON_ONCE(name->len > NAME_MAX) || 217 WARN_ON_ONCE(info->name2_len > 0)) 218 return; 219 220 info->name_len = name->len; 221 strcpy(fanotify_info_name(info), name->name); 222} 223 224static inline void fanotify_info_copy_name2(struct fanotify_info *info, 225 const struct qstr *name) 226{ 227 if (WARN_ON_ONCE(name->len > NAME_MAX)) 228 return; 229 230 info->name2_len = name->len; 231 strcpy(fanotify_info_name2(info), name->name); 232} 233 234/* 235 * Common structure for fanotify events. Concrete structs are allocated in 236 * fanotify_handle_event() and freed when the information is retrieved by 237 * userspace. The type of event determines how it was allocated, how it will 238 * be freed and which concrete struct it may be cast to. 239 */ 240enum fanotify_event_type { 241 FANOTIFY_EVENT_TYPE_FID, /* fixed length */ 242 FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */ 243 FANOTIFY_EVENT_TYPE_PATH, 244 FANOTIFY_EVENT_TYPE_PATH_PERM, 245 FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */ 246 FANOTIFY_EVENT_TYPE_FS_ERROR, /* struct fanotify_error_event */ 247 __FANOTIFY_EVENT_TYPE_NUM 248}; 249 250#define FANOTIFY_EVENT_TYPE_BITS \ 251 (ilog2(__FANOTIFY_EVENT_TYPE_NUM - 1) + 1) 252#define FANOTIFY_EVENT_HASH_BITS \ 253 (32 - FANOTIFY_EVENT_TYPE_BITS) 254 255struct fanotify_event { 256 struct fsnotify_event fse; 257 struct hlist_node merge_list; /* List for hashed merge */ 258 u32 mask; 259 struct { 260 unsigned int type : FANOTIFY_EVENT_TYPE_BITS; 261 unsigned int hash : FANOTIFY_EVENT_HASH_BITS; 262 }; 263 struct pid *pid; 264}; 265 266static inline void fanotify_init_event(struct fanotify_event *event, 267 unsigned int hash, u32 mask) 268{ 269 fsnotify_init_event(&event->fse); 270 INIT_HLIST_NODE(&event->merge_list); 271 event->hash = hash; 272 event->mask = mask; 273 event->pid = NULL; 274} 275 276#define FANOTIFY_INLINE_FH(name, size) \ 277struct { \ 278 struct fanotify_fh (name); \ 279 /* Space for object_fh.buf[] - access with fanotify_fh_buf() */ \ 280 unsigned char _inline_fh_buf[(size)]; \ 281} 282 283struct fanotify_fid_event { 284 struct fanotify_event fae; 285 __kernel_fsid_t fsid; 286 287 FANOTIFY_INLINE_FH(object_fh, FANOTIFY_INLINE_FH_LEN); 288}; 289 290static inline struct fanotify_fid_event * 291FANOTIFY_FE(struct fanotify_event *event) 292{ 293 return container_of(event, struct fanotify_fid_event, fae); 294} 295 296struct fanotify_name_event { 297 struct fanotify_event fae; 298 __kernel_fsid_t fsid; 299 struct fanotify_info info; 300}; 301 302static inline struct fanotify_name_event * 303FANOTIFY_NE(struct fanotify_event *event) 304{ 305 return container_of(event, struct fanotify_name_event, fae); 306} 307 308struct fanotify_error_event { 309 struct fanotify_event fae; 310 s32 error; /* Error reported by the Filesystem. */ 311 u32 err_count; /* Suppressed errors count */ 312 313 __kernel_fsid_t fsid; /* FSID this error refers to. */ 314 315 FANOTIFY_INLINE_FH(object_fh, MAX_HANDLE_SZ); 316}; 317 318static inline struct fanotify_error_event * 319FANOTIFY_EE(struct fanotify_event *event) 320{ 321 return container_of(event, struct fanotify_error_event, fae); 322} 323 324static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event) 325{ 326 if (event->type == FANOTIFY_EVENT_TYPE_FID) 327 return &FANOTIFY_FE(event)->fsid; 328 else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 329 return &FANOTIFY_NE(event)->fsid; 330 else if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) 331 return &FANOTIFY_EE(event)->fsid; 332 else 333 return NULL; 334} 335 336static inline struct fanotify_fh *fanotify_event_object_fh( 337 struct fanotify_event *event) 338{ 339 if (event->type == FANOTIFY_EVENT_TYPE_FID) 340 return &FANOTIFY_FE(event)->object_fh; 341 else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 342 return fanotify_info_file_fh(&FANOTIFY_NE(event)->info); 343 else if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) 344 return &FANOTIFY_EE(event)->object_fh; 345 else 346 return NULL; 347} 348 349static inline struct fanotify_info *fanotify_event_info( 350 struct fanotify_event *event) 351{ 352 if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 353 return &FANOTIFY_NE(event)->info; 354 else 355 return NULL; 356} 357 358static inline int fanotify_event_object_fh_len(struct fanotify_event *event) 359{ 360 struct fanotify_info *info = fanotify_event_info(event); 361 struct fanotify_fh *fh = fanotify_event_object_fh(event); 362 363 if (info) 364 return info->file_fh_totlen ? fh->len : 0; 365 else 366 return fh ? fh->len : 0; 367} 368 369static inline int fanotify_event_dir_fh_len(struct fanotify_event *event) 370{ 371 struct fanotify_info *info = fanotify_event_info(event); 372 373 return info ? fanotify_info_dir_fh_len(info) : 0; 374} 375 376static inline int fanotify_event_dir2_fh_len(struct fanotify_event *event) 377{ 378 struct fanotify_info *info = fanotify_event_info(event); 379 380 return info ? fanotify_info_dir2_fh_len(info) : 0; 381} 382 383static inline bool fanotify_event_has_object_fh(struct fanotify_event *event) 384{ 385 /* For error events, even zeroed fh are reported. */ 386 if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) 387 return true; 388 return fanotify_event_object_fh_len(event) > 0; 389} 390 391static inline bool fanotify_event_has_dir_fh(struct fanotify_event *event) 392{ 393 return fanotify_event_dir_fh_len(event) > 0; 394} 395 396static inline bool fanotify_event_has_dir2_fh(struct fanotify_event *event) 397{ 398 return fanotify_event_dir2_fh_len(event) > 0; 399} 400 401static inline bool fanotify_event_has_any_dir_fh(struct fanotify_event *event) 402{ 403 return fanotify_event_has_dir_fh(event) || 404 fanotify_event_has_dir2_fh(event); 405} 406 407struct fanotify_path_event { 408 struct fanotify_event fae; 409 struct path path; 410}; 411 412static inline struct fanotify_path_event * 413FANOTIFY_PE(struct fanotify_event *event) 414{ 415 return container_of(event, struct fanotify_path_event, fae); 416} 417 418/* 419 * Structure for permission fanotify events. It gets allocated and freed in 420 * fanotify_handle_event() since we wait there for user response. When the 421 * information is retrieved by userspace the structure is moved from 422 * group->notification_list to group->fanotify_data.access_list to wait for 423 * user response. 424 */ 425struct fanotify_perm_event { 426 struct fanotify_event fae; 427 struct path path; 428 unsigned short response; /* userspace answer to the event */ 429 unsigned short state; /* state of the event */ 430 int fd; /* fd we passed to userspace for this event */ 431}; 432 433static inline struct fanotify_perm_event * 434FANOTIFY_PERM(struct fanotify_event *event) 435{ 436 return container_of(event, struct fanotify_perm_event, fae); 437} 438 439static inline bool fanotify_is_perm_event(u32 mask) 440{ 441 return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) && 442 mask & FANOTIFY_PERM_EVENTS; 443} 444 445static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) 446{ 447 return container_of(fse, struct fanotify_event, fse); 448} 449 450static inline bool fanotify_is_error_event(u32 mask) 451{ 452 return mask & FAN_FS_ERROR; 453} 454 455static inline bool fanotify_event_has_path(struct fanotify_event *event) 456{ 457 return event->type == FANOTIFY_EVENT_TYPE_PATH || 458 event->type == FANOTIFY_EVENT_TYPE_PATH_PERM; 459} 460 461static inline struct path *fanotify_event_path(struct fanotify_event *event) 462{ 463 if (event->type == FANOTIFY_EVENT_TYPE_PATH) 464 return &FANOTIFY_PE(event)->path; 465 else if (event->type == FANOTIFY_EVENT_TYPE_PATH_PERM) 466 return &FANOTIFY_PERM(event)->path; 467 else 468 return NULL; 469} 470 471/* 472 * Use 128 size hash table to speed up events merge. 473 */ 474#define FANOTIFY_HTABLE_BITS (7) 475#define FANOTIFY_HTABLE_SIZE (1 << FANOTIFY_HTABLE_BITS) 476#define FANOTIFY_HTABLE_MASK (FANOTIFY_HTABLE_SIZE - 1) 477 478/* 479 * Permission events and overflow event do not get merged - don't hash them. 480 */ 481static inline bool fanotify_is_hashed_event(u32 mask) 482{ 483 return !(fanotify_is_perm_event(mask) || 484 fsnotify_is_overflow_event(mask)); 485} 486 487static inline unsigned int fanotify_event_hash_bucket( 488 struct fsnotify_group *group, 489 struct fanotify_event *event) 490{ 491 return event->hash & FANOTIFY_HTABLE_MASK; 492} 493 494static inline unsigned int fanotify_mark_user_flags(struct fsnotify_mark *mark) 495{ 496 unsigned int mflags = 0; 497 498 if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY) 499 mflags |= FAN_MARK_IGNORED_SURV_MODIFY; 500 if (mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF) 501 mflags |= FAN_MARK_EVICTABLE; 502 503 return mflags; 504}