Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'fsnotify_for_v5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify updates from Jan Kara:
"This implements the fanotify FAN_DIR_MODIFY event.

This event reports the name in a directory under which a change
happened and together with the directory filehandle and fstatat()
allows reliable and efficient implementation of directory
synchronization"

* tag 'fsnotify_for_v5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
fanotify: Fix the checks in fanotify_fsid_equal
fanotify: report name info for FAN_DIR_MODIFY event
fanotify: record name info for FAN_DIR_MODIFY event
fanotify: Drop fanotify_event_has_fid()
fanotify: prepare to report both parent and child fid's
fanotify: send FAN_DIR_MODIFY event flavor with dir inode and name
fanotify: divorce fanotify_path_event and fanotify_fid_event
fanotify: Store fanotify handles differently
fanotify: Simplify create_fd()
fanotify: fix merging marks masks with FAN_ONDIR
fanotify: merge duplicate events on parent and child
fsnotify: replace inode pointer with an object id
fsnotify: simplify arguments passing to fsnotify_parent()
fsnotify: use helpers to access data by data_type
fsnotify: funnel all dirent events through fsnotify_name()
fsnotify: factor helpers fsnotify_dentry() and fsnotify_file()
fsnotify: tidy up FS_ and FAN_ constants

+642 -368
+228 -74
fs/notify/fanotify/fanotify.c
··· 17 17 18 18 #include "fanotify.h" 19 19 20 + static bool fanotify_path_equal(struct path *p1, struct path *p2) 21 + { 22 + return p1->mnt == p2->mnt && p1->dentry == p2->dentry; 23 + } 24 + 25 + static inline bool fanotify_fsid_equal(__kernel_fsid_t *fsid1, 26 + __kernel_fsid_t *fsid2) 27 + { 28 + return fsid1->val[0] == fsid2->val[0] && fsid1->val[1] == fsid2->val[1]; 29 + } 30 + 31 + static bool fanotify_fh_equal(struct fanotify_fh *fh1, 32 + struct fanotify_fh *fh2) 33 + { 34 + if (fh1->type != fh2->type || fh1->len != fh2->len) 35 + return false; 36 + 37 + /* Do not merge events if we failed to encode fh */ 38 + if (fh1->type == FILEID_INVALID) 39 + return false; 40 + 41 + return !fh1->len || 42 + !memcmp(fanotify_fh_buf(fh1), fanotify_fh_buf(fh2), fh1->len); 43 + } 44 + 45 + static bool fanotify_fid_event_equal(struct fanotify_fid_event *ffe1, 46 + struct fanotify_fid_event *ffe2) 47 + { 48 + /* Do not merge fid events without object fh */ 49 + if (!ffe1->object_fh.len) 50 + return false; 51 + 52 + return fanotify_fsid_equal(&ffe1->fsid, &ffe2->fsid) && 53 + fanotify_fh_equal(&ffe1->object_fh, &ffe2->object_fh); 54 + } 55 + 56 + static bool fanotify_name_event_equal(struct fanotify_name_event *fne1, 57 + struct fanotify_name_event *fne2) 58 + { 59 + /* 60 + * Do not merge name events without dir fh. 61 + * FAN_DIR_MODIFY does not encode object fh, so it may be empty. 62 + */ 63 + if (!fne1->dir_fh.len) 64 + return false; 65 + 66 + if (fne1->name_len != fne2->name_len || 67 + !fanotify_fh_equal(&fne1->dir_fh, &fne2->dir_fh)) 68 + return false; 69 + 70 + return !memcmp(fne1->name, fne2->name, fne1->name_len); 71 + } 72 + 20 73 static bool should_merge(struct fsnotify_event *old_fsn, 21 74 struct fsnotify_event *new_fsn) 22 75 { ··· 79 26 old = FANOTIFY_E(old_fsn); 80 27 new = FANOTIFY_E(new_fsn); 81 28 82 - if (old_fsn->inode != new_fsn->inode || old->pid != new->pid || 83 - old->fh_type != new->fh_type || old->fh_len != new->fh_len) 29 + if (old_fsn->objectid != new_fsn->objectid || 30 + old->type != new->type || old->pid != new->pid) 84 31 return false; 85 32 86 - if (fanotify_event_has_path(old)) { 87 - return old->path.mnt == new->path.mnt && 88 - old->path.dentry == new->path.dentry; 89 - } else if (fanotify_event_has_fid(old)) { 33 + switch (old->type) { 34 + case FANOTIFY_EVENT_TYPE_PATH: 35 + return fanotify_path_equal(fanotify_event_path(old), 36 + fanotify_event_path(new)); 37 + case FANOTIFY_EVENT_TYPE_FID: 90 38 /* 91 39 * We want to merge many dirent events in the same dir (i.e. 92 40 * creates/unlinks/renames), but we do not want to merge dirent ··· 96 42 * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+ 97 43 * unlink pair or rmdir+create pair of events. 98 44 */ 99 - return (old->mask & FS_ISDIR) == (new->mask & FS_ISDIR) && 100 - fanotify_fid_equal(&old->fid, &new->fid, old->fh_len); 45 + if ((old->mask & FS_ISDIR) != (new->mask & FS_ISDIR)) 46 + return false; 47 + 48 + return fanotify_fid_event_equal(FANOTIFY_FE(old), 49 + FANOTIFY_FE(new)); 50 + case FANOTIFY_EVENT_TYPE_FID_NAME: 51 + return fanotify_name_event_equal(FANOTIFY_NE(old), 52 + FANOTIFY_NE(new)); 53 + default: 54 + WARN_ON_ONCE(1); 101 55 } 102 56 103 - /* Do not merge events if we failed to encode fid */ 104 57 return false; 105 58 } 106 59 ··· 212 151 { 213 152 __u32 marks_mask = 0, marks_ignored_mask = 0; 214 153 __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS; 215 - const struct path *path = data; 154 + const struct path *path = fsnotify_data_path(data, data_type); 216 155 struct fsnotify_mark *mark; 217 156 int type; 218 157 ··· 221 160 222 161 if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { 223 162 /* Do we have path to open a file descriptor? */ 224 - if (data_type != FSNOTIFY_EVENT_PATH) 163 + if (!path) 225 164 return 0; 226 165 /* Path type events are only relevant for files and dirs */ 227 166 if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry)) ··· 232 171 if (!fsnotify_iter_should_report_type(iter_info, type)) 233 172 continue; 234 173 mark = iter_info->marks[type]; 174 + /* 175 + * If the event is on dir and this mark doesn't care about 176 + * events on dir, don't send it! 177 + */ 178 + if (event_mask & FS_ISDIR && !(mark->mask & FS_ISDIR)) 179 + continue; 180 + 235 181 /* 236 182 * If the event is for a child and this mark doesn't care about 237 183 * events on a child, don't send it! ··· 255 187 test_mask = event_mask & marks_mask & ~marks_ignored_mask; 256 188 257 189 /* 258 - * dirent modification events (create/delete/move) do not carry the 259 - * child entry name/inode information. Instead, we report FAN_ONDIR 260 - * for mkdir/rmdir so user can differentiate them from creat/unlink. 190 + * For dirent modification events (create/delete/move) that do not carry 191 + * the child entry name information, we report FAN_ONDIR for mkdir/rmdir 192 + * so user can differentiate them from creat/unlink. 261 193 * 262 194 * For backward compatibility and consistency, do not report FAN_ONDIR 263 195 * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR ··· 271 203 user_mask &= ~FAN_ONDIR; 272 204 } 273 205 274 - if (event_mask & FS_ISDIR && 275 - !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) 276 - return 0; 277 - 278 206 return test_mask & user_mask; 279 207 } 280 208 281 - static int fanotify_encode_fid(struct fanotify_event *event, 282 - struct inode *inode, gfp_t gfp, 283 - __kernel_fsid_t *fsid) 209 + static void fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, 210 + gfp_t gfp) 284 211 { 285 - struct fanotify_fid *fid = &event->fid; 286 - int dwords, bytes = 0; 287 - int err, type; 212 + int dwords, type, bytes = 0; 213 + char *ext_buf = NULL; 214 + void *buf = fh->buf; 215 + int err; 288 216 289 - fid->ext_fh = NULL; 217 + if (!inode) 218 + goto out; 219 + 290 220 dwords = 0; 291 221 err = -ENOENT; 292 222 type = exportfs_encode_inode_fh(inode, NULL, &dwords, NULL); ··· 295 229 if (bytes > FANOTIFY_INLINE_FH_LEN) { 296 230 /* Treat failure to allocate fh as failure to allocate event */ 297 231 err = -ENOMEM; 298 - fid->ext_fh = kmalloc(bytes, gfp); 299 - if (!fid->ext_fh) 232 + ext_buf = kmalloc(bytes, gfp); 233 + if (!ext_buf) 300 234 goto out_err; 235 + 236 + *fanotify_fh_ext_buf_ptr(fh) = ext_buf; 237 + buf = ext_buf; 301 238 } 302 239 303 - type = exportfs_encode_inode_fh(inode, fanotify_fid_fh(fid, bytes), 304 - &dwords, NULL); 240 + type = exportfs_encode_inode_fh(inode, buf, &dwords, NULL); 305 241 err = -EINVAL; 306 242 if (!type || type == FILEID_INVALID || bytes != dwords << 2) 307 243 goto out_err; 308 244 309 - fid->fsid = *fsid; 310 - event->fh_len = bytes; 245 + fh->type = type; 246 + fh->len = bytes; 311 247 312 - return type; 248 + return; 313 249 314 250 out_err: 315 - pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, " 316 - "type=%d, bytes=%d, err=%i)\n", 317 - fsid->val[0], fsid->val[1], type, bytes, err); 318 - kfree(fid->ext_fh); 319 - fid->ext_fh = NULL; 320 - event->fh_len = 0; 321 - 322 - return FILEID_INVALID; 251 + pr_warn_ratelimited("fanotify: failed to encode fid (type=%d, len=%d, err=%i)\n", 252 + type, bytes, err); 253 + kfree(ext_buf); 254 + *fanotify_fh_ext_buf_ptr(fh) = NULL; 255 + out: 256 + /* Report the event without a file identifier on encode error */ 257 + fh->type = FILEID_INVALID; 258 + fh->len = 0; 323 259 } 324 260 325 261 /* ··· 337 269 { 338 270 if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS) 339 271 return to_tell; 340 - else if (data_type == FSNOTIFY_EVENT_INODE) 341 - return (struct inode *)data; 342 - else if (data_type == FSNOTIFY_EVENT_PATH) 343 - return d_inode(((struct path *)data)->dentry); 344 - return NULL; 272 + 273 + return (struct inode *)fsnotify_data_inode(data, data_type); 345 274 } 346 275 347 276 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, 348 277 struct inode *inode, u32 mask, 349 278 const void *data, int data_type, 279 + const struct qstr *file_name, 350 280 __kernel_fsid_t *fsid) 351 281 { 352 282 struct fanotify_event *event = NULL; 283 + struct fanotify_fid_event *ffe = NULL; 284 + struct fanotify_name_event *fne = NULL; 353 285 gfp_t gfp = GFP_KERNEL_ACCOUNT; 354 286 struct inode *id = fanotify_fid_inode(inode, mask, data, data_type); 287 + const struct path *path = fsnotify_data_path(data, data_type); 355 288 356 289 /* 357 290 * For queues with unlimited length lost events are not expected and ··· 374 305 pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp); 375 306 if (!pevent) 376 307 goto out; 308 + 377 309 event = &pevent->fae; 310 + event->type = FANOTIFY_EVENT_TYPE_PATH_PERM; 378 311 pevent->response = 0; 379 312 pevent->state = FAN_EVENT_INIT; 380 313 goto init; 381 314 } 382 - event = kmem_cache_alloc(fanotify_event_cachep, gfp); 383 - if (!event) 384 - goto out; 385 - init: __maybe_unused 386 - fsnotify_init_event(&event->fse, inode); 315 + 316 + /* 317 + * For FAN_DIR_MODIFY event, we report the fid of the directory and 318 + * the name of the modified entry. 319 + * Allocate an fanotify_name_event struct and copy the name. 320 + */ 321 + if (mask & FAN_DIR_MODIFY && !(WARN_ON_ONCE(!file_name))) { 322 + fne = kmalloc(sizeof(*fne) + file_name->len + 1, gfp); 323 + if (!fne) 324 + goto out; 325 + 326 + event = &fne->fae; 327 + event->type = FANOTIFY_EVENT_TYPE_FID_NAME; 328 + fne->name_len = file_name->len; 329 + strcpy(fne->name, file_name->name); 330 + goto init; 331 + } 332 + 333 + if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { 334 + ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp); 335 + if (!ffe) 336 + goto out; 337 + 338 + event = &ffe->fae; 339 + event->type = FANOTIFY_EVENT_TYPE_FID; 340 + } else { 341 + struct fanotify_path_event *pevent; 342 + 343 + pevent = kmem_cache_alloc(fanotify_path_event_cachep, gfp); 344 + if (!pevent) 345 + goto out; 346 + 347 + event = &pevent->fae; 348 + event->type = FANOTIFY_EVENT_TYPE_PATH; 349 + } 350 + 351 + init: 352 + /* 353 + * Use the victim inode instead of the watching inode as the id for 354 + * event queue, so event reported on parent is merged with event 355 + * reported on child when both directory and child watches exist. 356 + */ 357 + fsnotify_init_event(&event->fse, (unsigned long)id); 387 358 event->mask = mask; 388 359 if (FAN_GROUP_FLAG(group, FAN_REPORT_TID)) 389 360 event->pid = get_pid(task_pid(current)); 390 361 else 391 362 event->pid = get_pid(task_tgid(current)); 392 - event->fh_len = 0; 393 - if (id && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { 394 - /* Report the event without a file identifier on encode error */ 395 - event->fh_type = fanotify_encode_fid(event, id, gfp, fsid); 396 - } else if (data_type == FSNOTIFY_EVENT_PATH) { 397 - event->fh_type = FILEID_ROOT; 398 - event->path = *((struct path *)data); 399 - path_get(&event->path); 400 - } else { 401 - event->fh_type = FILEID_INVALID; 402 - event->path.mnt = NULL; 403 - event->path.dentry = NULL; 363 + 364 + if (fsid && fanotify_event_fsid(event)) 365 + *fanotify_event_fsid(event) = *fsid; 366 + 367 + if (fanotify_event_object_fh(event)) 368 + fanotify_encode_fh(fanotify_event_object_fh(event), id, gfp); 369 + 370 + if (fanotify_event_dir_fh(event)) 371 + fanotify_encode_fh(fanotify_event_dir_fh(event), id, gfp); 372 + 373 + if (fanotify_event_has_path(event)) { 374 + struct path *p = fanotify_event_path(event); 375 + 376 + if (path) { 377 + *p = *path; 378 + path_get(path); 379 + } else { 380 + p->mnt = NULL; 381 + p->dentry = NULL; 382 + } 404 383 } 405 384 out: 406 385 memalloc_unuse_memcg(); ··· 509 392 BUILD_BUG_ON(FAN_MOVED_FROM != FS_MOVED_FROM); 510 393 BUILD_BUG_ON(FAN_CREATE != FS_CREATE); 511 394 BUILD_BUG_ON(FAN_DELETE != FS_DELETE); 395 + BUILD_BUG_ON(FAN_DIR_MODIFY != FS_DIR_MODIFY); 512 396 BUILD_BUG_ON(FAN_DELETE_SELF != FS_DELETE_SELF); 513 397 BUILD_BUG_ON(FAN_MOVE_SELF != FS_MOVE_SELF); 514 398 BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD); ··· 520 402 BUILD_BUG_ON(FAN_OPEN_EXEC != FS_OPEN_EXEC); 521 403 BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM); 522 404 523 - BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19); 405 + BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 20); 524 406 525 407 mask = fanotify_group_event_mask(group, iter_info, mask, data, 526 408 data_type); ··· 547 429 } 548 430 549 431 event = fanotify_alloc_event(group, inode, mask, data, data_type, 550 - &fsid); 432 + file_name, &fsid); 551 433 ret = -ENOMEM; 552 434 if (unlikely(!event)) { 553 435 /* ··· 569 451 570 452 ret = 0; 571 453 } else if (fanotify_is_perm_event(mask)) { 572 - ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event), 454 + ret = fanotify_get_response(group, FANOTIFY_PERM(event), 573 455 iter_info); 574 456 } 575 457 finish: ··· 588 470 free_uid(user); 589 471 } 590 472 473 + static void fanotify_free_path_event(struct fanotify_event *event) 474 + { 475 + path_put(fanotify_event_path(event)); 476 + kmem_cache_free(fanotify_path_event_cachep, FANOTIFY_PE(event)); 477 + } 478 + 479 + static void fanotify_free_perm_event(struct fanotify_event *event) 480 + { 481 + path_put(fanotify_event_path(event)); 482 + kmem_cache_free(fanotify_perm_event_cachep, FANOTIFY_PERM(event)); 483 + } 484 + 485 + static void fanotify_free_fid_event(struct fanotify_event *event) 486 + { 487 + struct fanotify_fid_event *ffe = FANOTIFY_FE(event); 488 + 489 + if (fanotify_fh_has_ext_buf(&ffe->object_fh)) 490 + kfree(fanotify_fh_ext_buf(&ffe->object_fh)); 491 + kmem_cache_free(fanotify_fid_event_cachep, ffe); 492 + } 493 + 494 + static void fanotify_free_name_event(struct fanotify_event *event) 495 + { 496 + struct fanotify_name_event *fne = FANOTIFY_NE(event); 497 + 498 + if (fanotify_fh_has_ext_buf(&fne->dir_fh)) 499 + kfree(fanotify_fh_ext_buf(&fne->dir_fh)); 500 + kfree(fne); 501 + } 502 + 591 503 static void fanotify_free_event(struct fsnotify_event *fsn_event) 592 504 { 593 505 struct fanotify_event *event; 594 506 595 507 event = FANOTIFY_E(fsn_event); 596 - if (fanotify_event_has_path(event)) 597 - path_put(&event->path); 598 - else if (fanotify_event_has_ext_fh(event)) 599 - kfree(event->fid.ext_fh); 600 508 put_pid(event->pid); 601 - if (fanotify_is_perm_event(event->mask)) { 602 - kmem_cache_free(fanotify_perm_event_cachep, 603 - FANOTIFY_PE(fsn_event)); 604 - return; 509 + switch (event->type) { 510 + case FANOTIFY_EVENT_TYPE_PATH: 511 + fanotify_free_path_event(event); 512 + break; 513 + case FANOTIFY_EVENT_TYPE_PATH_PERM: 514 + fanotify_free_perm_event(event); 515 + break; 516 + case FANOTIFY_EVENT_TYPE_FID: 517 + fanotify_free_fid_event(event); 518 + break; 519 + case FANOTIFY_EVENT_TYPE_FID_NAME: 520 + fanotify_free_name_event(event); 521 + break; 522 + default: 523 + WARN_ON_ONCE(1); 605 524 } 606 - kmem_cache_free(fanotify_event_cachep, event); 607 525 } 608 526 609 527 static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
+127 -62
fs/notify/fanotify/fanotify.h
··· 5 5 #include <linux/exportfs.h> 6 6 7 7 extern struct kmem_cache *fanotify_mark_cache; 8 - extern struct kmem_cache *fanotify_event_cachep; 8 + extern struct kmem_cache *fanotify_fid_event_cachep; 9 + extern struct kmem_cache *fanotify_path_event_cachep; 9 10 extern struct kmem_cache *fanotify_perm_event_cachep; 10 11 11 12 /* Possible states of the permission event */ ··· 19 18 20 19 /* 21 20 * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation). 22 - * For 32bit arch, fid increases the size of fanotify_event by 12 bytes and 23 - * fh_* fields increase the size of fanotify_event by another 4 bytes. 24 - * For 64bit arch, fid increases the size of fanotify_fid by 8 bytes and 25 - * fh_* fields are packed in a hole after mask. 21 + * fh buf should be dword aligned. On 64bit arch, the ext_buf pointer is 22 + * stored in either the first or last 2 dwords. 26 23 */ 27 - #if BITS_PER_LONG == 32 28 24 #define FANOTIFY_INLINE_FH_LEN (3 << 2) 29 - #else 30 - #define FANOTIFY_INLINE_FH_LEN (4 << 2) 31 - #endif 32 25 33 - struct fanotify_fid { 34 - __kernel_fsid_t fsid; 35 - union { 36 - unsigned char fh[FANOTIFY_INLINE_FH_LEN]; 37 - unsigned char *ext_fh; 38 - }; 39 - }; 26 + struct fanotify_fh { 27 + unsigned char buf[FANOTIFY_INLINE_FH_LEN]; 28 + u8 type; 29 + u8 len; 30 + } __aligned(4); 40 31 41 - static inline void *fanotify_fid_fh(struct fanotify_fid *fid, 42 - unsigned int fh_len) 32 + static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh) 43 33 { 44 - return fh_len <= FANOTIFY_INLINE_FH_LEN ? fid->fh : fid->ext_fh; 34 + return fh->len > FANOTIFY_INLINE_FH_LEN; 45 35 } 46 36 47 - static inline bool fanotify_fid_equal(struct fanotify_fid *fid1, 48 - struct fanotify_fid *fid2, 49 - unsigned int fh_len) 37 + static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh) 50 38 { 51 - return fid1->fsid.val[0] == fid2->fsid.val[0] && 52 - fid1->fsid.val[1] == fid2->fsid.val[1] && 53 - !memcmp(fanotify_fid_fh(fid1, fh_len), 54 - fanotify_fid_fh(fid2, fh_len), fh_len); 39 + BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) > 40 + FANOTIFY_INLINE_FH_LEN); 41 + return (char **)ALIGN((unsigned long)(fh->buf), __alignof__(char *)); 42 + } 43 + 44 + static inline void *fanotify_fh_ext_buf(struct fanotify_fh *fh) 45 + { 46 + return *fanotify_fh_ext_buf_ptr(fh); 47 + } 48 + 49 + static inline void *fanotify_fh_buf(struct fanotify_fh *fh) 50 + { 51 + return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh->buf; 55 52 } 56 53 57 54 /* 58 - * Structure for normal fanotify events. It gets allocated in 55 + * Common structure for fanotify events. Concrete structs are allocated in 59 56 * fanotify_handle_event() and freed when the information is retrieved by 60 - * userspace 57 + * userspace. The type of event determines how it was allocated, how it will 58 + * be freed and which concrete struct it may be cast to. 61 59 */ 60 + enum fanotify_event_type { 61 + FANOTIFY_EVENT_TYPE_FID, /* fixed length */ 62 + FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */ 63 + FANOTIFY_EVENT_TYPE_PATH, 64 + FANOTIFY_EVENT_TYPE_PATH_PERM, 65 + }; 66 + 62 67 struct fanotify_event { 63 68 struct fsnotify_event fse; 64 69 u32 mask; 65 - /* 66 - * Those fields are outside fanotify_fid to pack fanotify_event nicely 67 - * on 64bit arch and to use fh_type as an indication of whether path 68 - * or fid are used in the union: 69 - * FILEID_ROOT (0) for path, > 0 for fid, FILEID_INVALID for neither. 70 - */ 71 - u8 fh_type; 72 - u8 fh_len; 73 - u16 pad; 74 - union { 75 - /* 76 - * We hold ref to this path so it may be dereferenced at any 77 - * point during this object's lifetime 78 - */ 79 - struct path path; 80 - /* 81 - * With FAN_REPORT_FID, we do not hold any reference on the 82 - * victim object. Instead we store its NFS file handle and its 83 - * filesystem's fsid as a unique identifier. 84 - */ 85 - struct fanotify_fid fid; 86 - }; 70 + enum fanotify_event_type type; 87 71 struct pid *pid; 88 72 }; 89 73 90 - static inline bool fanotify_event_has_path(struct fanotify_event *event) 74 + struct fanotify_fid_event { 75 + struct fanotify_event fae; 76 + __kernel_fsid_t fsid; 77 + struct fanotify_fh object_fh; 78 + }; 79 + 80 + static inline struct fanotify_fid_event * 81 + FANOTIFY_FE(struct fanotify_event *event) 91 82 { 92 - return event->fh_type == FILEID_ROOT; 83 + return container_of(event, struct fanotify_fid_event, fae); 93 84 } 94 85 95 - static inline bool fanotify_event_has_fid(struct fanotify_event *event) 86 + struct fanotify_name_event { 87 + struct fanotify_event fae; 88 + __kernel_fsid_t fsid; 89 + struct fanotify_fh dir_fh; 90 + u8 name_len; 91 + char name[0]; 92 + }; 93 + 94 + static inline struct fanotify_name_event * 95 + FANOTIFY_NE(struct fanotify_event *event) 96 96 { 97 - return event->fh_type != FILEID_ROOT && 98 - event->fh_type != FILEID_INVALID; 97 + return container_of(event, struct fanotify_name_event, fae); 99 98 } 100 99 101 - static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event) 100 + static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event) 102 101 { 103 - return fanotify_event_has_fid(event) && 104 - event->fh_len > FANOTIFY_INLINE_FH_LEN; 102 + if (event->type == FANOTIFY_EVENT_TYPE_FID) 103 + return &FANOTIFY_FE(event)->fsid; 104 + else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 105 + return &FANOTIFY_NE(event)->fsid; 106 + else 107 + return NULL; 105 108 } 106 109 107 - static inline void *fanotify_event_fh(struct fanotify_event *event) 110 + static inline struct fanotify_fh *fanotify_event_object_fh( 111 + struct fanotify_event *event) 108 112 { 109 - return fanotify_fid_fh(&event->fid, event->fh_len); 113 + if (event->type == FANOTIFY_EVENT_TYPE_FID) 114 + return &FANOTIFY_FE(event)->object_fh; 115 + else 116 + return NULL; 117 + } 118 + 119 + static inline struct fanotify_fh *fanotify_event_dir_fh( 120 + struct fanotify_event *event) 121 + { 122 + if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) 123 + return &FANOTIFY_NE(event)->dir_fh; 124 + else 125 + return NULL; 126 + } 127 + 128 + static inline int fanotify_event_object_fh_len(struct fanotify_event *event) 129 + { 130 + struct fanotify_fh *fh = fanotify_event_object_fh(event); 131 + 132 + return fh ? fh->len : 0; 133 + } 134 + 135 + static inline bool fanotify_event_has_name(struct fanotify_event *event) 136 + { 137 + return event->type == FANOTIFY_EVENT_TYPE_FID_NAME; 138 + } 139 + 140 + static inline int fanotify_event_name_len(struct fanotify_event *event) 141 + { 142 + return fanotify_event_has_name(event) ? 143 + FANOTIFY_NE(event)->name_len : 0; 144 + } 145 + 146 + struct fanotify_path_event { 147 + struct fanotify_event fae; 148 + struct path path; 149 + }; 150 + 151 + static inline struct fanotify_path_event * 152 + FANOTIFY_PE(struct fanotify_event *event) 153 + { 154 + return container_of(event, struct fanotify_path_event, fae); 110 155 } 111 156 112 157 /* ··· 164 117 */ 165 118 struct fanotify_perm_event { 166 119 struct fanotify_event fae; 120 + struct path path; 167 121 unsigned short response; /* userspace answer to the event */ 168 122 unsigned short state; /* state of the event */ 169 123 int fd; /* fd we passed to userspace for this event */ 170 124 }; 171 125 172 126 static inline struct fanotify_perm_event * 173 - FANOTIFY_PE(struct fsnotify_event *fse) 127 + FANOTIFY_PERM(struct fanotify_event *event) 174 128 { 175 - return container_of(fse, struct fanotify_perm_event, fae.fse); 129 + return container_of(event, struct fanotify_perm_event, fae); 176 130 } 177 131 178 132 static inline bool fanotify_is_perm_event(u32 mask) ··· 187 139 return container_of(fse, struct fanotify_event, fse); 188 140 } 189 141 142 + static inline bool fanotify_event_has_path(struct fanotify_event *event) 143 + { 144 + return event->type == FANOTIFY_EVENT_TYPE_PATH || 145 + event->type == FANOTIFY_EVENT_TYPE_PATH_PERM; 146 + } 147 + 148 + static inline struct path *fanotify_event_path(struct fanotify_event *event) 149 + { 150 + if (event->type == FANOTIFY_EVENT_TYPE_PATH) 151 + return &FANOTIFY_PE(event)->path; 152 + else if (event->type == FANOTIFY_EVENT_TYPE_PATH_PERM) 153 + return &FANOTIFY_PERM(event)->path; 154 + else 155 + return NULL; 156 + } 157 + 190 158 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, 191 159 struct inode *inode, u32 mask, 192 160 const void *data, int data_type, 161 + const struct qstr *file_name, 193 162 __kernel_fsid_t *fsid);
+150 -80
fs/notify/fanotify/fanotify_user.c
··· 46 46 extern const struct fsnotify_ops fanotify_fsnotify_ops; 47 47 48 48 struct kmem_cache *fanotify_mark_cache __read_mostly; 49 - struct kmem_cache *fanotify_event_cachep __read_mostly; 49 + struct kmem_cache *fanotify_fid_event_cachep __read_mostly; 50 + struct kmem_cache *fanotify_path_event_cachep __read_mostly; 50 51 struct kmem_cache *fanotify_perm_event_cachep __read_mostly; 51 52 52 53 #define FANOTIFY_EVENT_ALIGN 4 54 + #define FANOTIFY_INFO_HDR_LEN \ 55 + (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle)) 56 + 57 + static int fanotify_fid_info_len(int fh_len, int name_len) 58 + { 59 + int info_len = fh_len; 60 + 61 + if (name_len) 62 + info_len += name_len + 1; 63 + 64 + return roundup(FANOTIFY_INFO_HDR_LEN + info_len, FANOTIFY_EVENT_ALIGN); 65 + } 53 66 54 67 static int fanotify_event_info_len(struct fanotify_event *event) 55 68 { 56 - if (!fanotify_event_has_fid(event)) 57 - return 0; 69 + int info_len = 0; 70 + int fh_len = fanotify_event_object_fh_len(event); 58 71 59 - return roundup(sizeof(struct fanotify_event_info_fid) + 60 - sizeof(struct file_handle) + event->fh_len, 61 - FANOTIFY_EVENT_ALIGN); 72 + if (fh_len) 73 + info_len += fanotify_fid_info_len(fh_len, 0); 74 + 75 + if (fanotify_event_name_len(event)) { 76 + struct fanotify_name_event *fne = FANOTIFY_NE(event); 77 + 78 + info_len += fanotify_fid_info_len(fne->dir_fh.len, 79 + fne->name_len); 80 + } 81 + 82 + return info_len; 62 83 } 63 84 64 85 /* 65 - * Get an fsnotify notification event if one exists and is small 86 + * Get an fanotify notification event if one exists and is small 66 87 * enough to fit in "count". Return an error pointer if the count 67 88 * is not large enough. When permission event is dequeued, its state is 68 89 * updated accordingly. 69 90 */ 70 - static struct fsnotify_event *get_one_event(struct fsnotify_group *group, 91 + static struct fanotify_event *get_one_event(struct fsnotify_group *group, 71 92 size_t count) 72 93 { 73 94 size_t event_size = FAN_EVENT_METADATA_LEN; 74 - struct fsnotify_event *fsn_event = NULL; 95 + struct fanotify_event *event = NULL; 75 96 76 97 pr_debug("%s: group=%p count=%zd\n", __func__, group, count); 77 98 ··· 106 85 } 107 86 108 87 if (event_size > count) { 109 - fsn_event = ERR_PTR(-EINVAL); 88 + event = ERR_PTR(-EINVAL); 110 89 goto out; 111 90 } 112 - fsn_event = fsnotify_remove_first_event(group); 113 - if (fanotify_is_perm_event(FANOTIFY_E(fsn_event)->mask)) 114 - FANOTIFY_PE(fsn_event)->state = FAN_EVENT_REPORTED; 91 + event = FANOTIFY_E(fsnotify_remove_first_event(group)); 92 + if (fanotify_is_perm_event(event->mask)) 93 + FANOTIFY_PERM(event)->state = FAN_EVENT_REPORTED; 115 94 out: 116 95 spin_unlock(&group->notification_lock); 117 - return fsn_event; 96 + return event; 118 97 } 119 98 120 - static int create_fd(struct fsnotify_group *group, 121 - struct fanotify_event *event, 99 + static int create_fd(struct fsnotify_group *group, struct path *path, 122 100 struct file **file) 123 101 { 124 102 int client_fd; 125 103 struct file *new_file; 126 - 127 - pr_debug("%s: group=%p event=%p\n", __func__, group, event); 128 104 129 105 client_fd = get_unused_fd_flags(group->fanotify_data.f_flags); 130 106 if (client_fd < 0) ··· 131 113 * we need a new file handle for the userspace program so it can read even if it was 132 114 * originally opened O_WRONLY. 133 115 */ 134 - /* it's possible this event was an overflow event. in that case dentry and mnt 135 - * are NULL; That's fine, just don't call dentry open */ 136 - if (event->path.dentry && event->path.mnt) 137 - new_file = dentry_open(&event->path, 138 - group->fanotify_data.f_flags | FMODE_NONOTIFY, 139 - current_cred()); 140 - else 141 - new_file = ERR_PTR(-EOVERFLOW); 116 + new_file = dentry_open(path, 117 + group->fanotify_data.f_flags | FMODE_NONOTIFY, 118 + current_cred()); 142 119 if (IS_ERR(new_file)) { 143 120 /* 144 121 * we still send an event even if we can't open the file. this ··· 217 204 return -ENOENT; 218 205 } 219 206 220 - static int copy_fid_to_user(struct fanotify_event *event, char __user *buf) 207 + static int copy_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, 208 + const char *name, size_t name_len, 209 + char __user *buf, size_t count) 221 210 { 222 211 struct fanotify_event_info_fid info = { }; 223 212 struct file_handle handle = { }; 224 - unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh; 225 - size_t fh_len = event->fh_len; 226 - size_t len = fanotify_event_info_len(event); 213 + unsigned char bounce[FANOTIFY_INLINE_FH_LEN], *fh_buf; 214 + size_t fh_len = fh ? fh->len : 0; 215 + size_t info_len = fanotify_fid_info_len(fh_len, name_len); 216 + size_t len = info_len; 227 217 228 - if (!len) 218 + pr_debug("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n", 219 + __func__, fh_len, name_len, info_len, count); 220 + 221 + if (!fh_len || (name && !name_len)) 229 222 return 0; 230 223 231 - if (WARN_ON_ONCE(len < sizeof(info) + sizeof(handle) + fh_len)) 224 + if (WARN_ON_ONCE(len < sizeof(info) || len > count)) 232 225 return -EFAULT; 233 226 234 - /* Copy event info fid header followed by vaiable sized file handle */ 235 - info.hdr.info_type = FAN_EVENT_INFO_TYPE_FID; 227 + /* 228 + * Copy event info fid header followed by variable sized file handle 229 + * and optionally followed by variable sized filename. 230 + */ 231 + info.hdr.info_type = name_len ? FAN_EVENT_INFO_TYPE_DFID_NAME : 232 + FAN_EVENT_INFO_TYPE_FID; 236 233 info.hdr.len = len; 237 - info.fsid = event->fid.fsid; 234 + info.fsid = *fsid; 238 235 if (copy_to_user(buf, &info, sizeof(info))) 239 236 return -EFAULT; 240 237 241 238 buf += sizeof(info); 242 239 len -= sizeof(info); 243 - handle.handle_type = event->fh_type; 240 + if (WARN_ON_ONCE(len < sizeof(handle))) 241 + return -EFAULT; 242 + 243 + handle.handle_type = fh->type; 244 244 handle.handle_bytes = fh_len; 245 245 if (copy_to_user(buf, &handle, sizeof(handle))) 246 246 return -EFAULT; 247 247 248 248 buf += sizeof(handle); 249 249 len -= sizeof(handle); 250 - /* 251 - * For an inline fh, copy through stack to exclude the copy from 252 - * usercopy hardening protections. 253 - */ 254 - fh = fanotify_event_fh(event); 255 - if (fh_len <= FANOTIFY_INLINE_FH_LEN) { 256 - memcpy(bounce, fh, fh_len); 257 - fh = bounce; 258 - } 259 - if (copy_to_user(buf, fh, fh_len)) 250 + if (WARN_ON_ONCE(len < fh_len)) 260 251 return -EFAULT; 261 252 262 - /* Pad with 0's */ 253 + /* 254 + * For an inline fh and inline file name, copy through stack to exclude 255 + * the copy from usercopy hardening protections. 256 + */ 257 + fh_buf = fanotify_fh_buf(fh); 258 + if (fh_len <= FANOTIFY_INLINE_FH_LEN) { 259 + memcpy(bounce, fh_buf, fh_len); 260 + fh_buf = bounce; 261 + } 262 + if (copy_to_user(buf, fh_buf, fh_len)) 263 + return -EFAULT; 264 + 263 265 buf += fh_len; 264 266 len -= fh_len; 267 + 268 + if (name_len) { 269 + /* Copy the filename with terminating null */ 270 + name_len++; 271 + if (WARN_ON_ONCE(len < name_len)) 272 + return -EFAULT; 273 + 274 + if (copy_to_user(buf, name, name_len)) 275 + return -EFAULT; 276 + 277 + buf += name_len; 278 + len -= name_len; 279 + } 280 + 281 + /* Pad with 0's */ 265 282 WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN); 266 283 if (len > 0 && clear_user(buf, len)) 267 284 return -EFAULT; 268 285 269 - return 0; 286 + return info_len; 270 287 } 271 288 272 289 static ssize_t copy_event_to_user(struct fsnotify_group *group, 273 - struct fsnotify_event *fsn_event, 290 + struct fanotify_event *event, 274 291 char __user *buf, size_t count) 275 292 { 276 293 struct fanotify_event_metadata metadata; 277 - struct fanotify_event *event; 294 + struct path *path = fanotify_event_path(event); 278 295 struct file *f = NULL; 279 296 int ret, fd = FAN_NOFD; 280 297 281 - pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event); 298 + pr_debug("%s: group=%p event=%p\n", __func__, group, event); 282 299 283 - event = container_of(fsn_event, struct fanotify_event, fse); 284 - metadata.event_len = FAN_EVENT_METADATA_LEN; 300 + metadata.event_len = FAN_EVENT_METADATA_LEN + 301 + fanotify_event_info_len(event); 285 302 metadata.metadata_len = FAN_EVENT_METADATA_LEN; 286 303 metadata.vers = FANOTIFY_METADATA_VERSION; 287 304 metadata.reserved = 0; 288 305 metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS; 289 306 metadata.pid = pid_vnr(event->pid); 290 307 291 - if (fanotify_event_has_path(event)) { 292 - fd = create_fd(group, event, &f); 308 + if (path && path->mnt && path->dentry) { 309 + fd = create_fd(group, path, &f); 293 310 if (fd < 0) 294 311 return fd; 295 - } else if (fanotify_event_has_fid(event)) { 296 - metadata.event_len += fanotify_event_info_len(event); 297 312 } 298 313 metadata.fd = fd; 299 314 ··· 336 295 if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN)) 337 296 goto out_close_fd; 338 297 339 - if (fanotify_is_perm_event(event->mask)) 340 - FANOTIFY_PE(fsn_event)->fd = fd; 298 + buf += FAN_EVENT_METADATA_LEN; 299 + count -= FAN_EVENT_METADATA_LEN; 341 300 342 - if (fanotify_event_has_path(event)) { 301 + if (fanotify_is_perm_event(event->mask)) 302 + FANOTIFY_PERM(event)->fd = fd; 303 + 304 + if (f) 343 305 fd_install(fd, f); 344 - } else if (fanotify_event_has_fid(event)) { 345 - ret = copy_fid_to_user(event, buf + FAN_EVENT_METADATA_LEN); 306 + 307 + /* Event info records order is: dir fid + name, child fid */ 308 + if (fanotify_event_name_len(event)) { 309 + struct fanotify_name_event *fne = FANOTIFY_NE(event); 310 + 311 + ret = copy_info_to_user(fanotify_event_fsid(event), 312 + fanotify_event_dir_fh(event), 313 + fne->name, fne->name_len, 314 + buf, count); 346 315 if (ret < 0) 347 316 return ret; 317 + 318 + buf += ret; 319 + count -= ret; 320 + } 321 + 322 + if (fanotify_event_object_fh_len(event)) { 323 + ret = copy_info_to_user(fanotify_event_fsid(event), 324 + fanotify_event_object_fh(event), 325 + NULL, 0, buf, count); 326 + if (ret < 0) 327 + return ret; 328 + 329 + buf += ret; 330 + count -= ret; 348 331 } 349 332 350 333 return metadata.event_len; ··· 400 335 size_t count, loff_t *pos) 401 336 { 402 337 struct fsnotify_group *group; 403 - struct fsnotify_event *kevent; 338 + struct fanotify_event *event; 404 339 char __user *start; 405 340 int ret; 406 341 DEFINE_WAIT_FUNC(wait, woken_wake_function); ··· 412 347 413 348 add_wait_queue(&group->notification_waitq, &wait); 414 349 while (1) { 415 - kevent = get_one_event(group, count); 416 - if (IS_ERR(kevent)) { 417 - ret = PTR_ERR(kevent); 350 + event = get_one_event(group, count); 351 + if (IS_ERR(event)) { 352 + ret = PTR_ERR(event); 418 353 break; 419 354 } 420 355 421 - if (!kevent) { 356 + if (!event) { 422 357 ret = -EAGAIN; 423 358 if (file->f_flags & O_NONBLOCK) 424 359 break; ··· 434 369 continue; 435 370 } 436 371 437 - ret = copy_event_to_user(group, kevent, buf, count); 372 + ret = copy_event_to_user(group, event, buf, count); 438 373 if (unlikely(ret == -EOPENSTALE)) { 439 374 /* 440 375 * We cannot report events with stale fd so drop it. ··· 449 384 * Permission events get queued to wait for response. Other 450 385 * events can be destroyed now. 451 386 */ 452 - if (!fanotify_is_perm_event(FANOTIFY_E(kevent)->mask)) { 453 - fsnotify_destroy_event(group, kevent); 387 + if (!fanotify_is_perm_event(event->mask)) { 388 + fsnotify_destroy_event(group, &event->fse); 454 389 } else { 455 390 if (ret <= 0) { 456 391 spin_lock(&group->notification_lock); 457 392 finish_permission_event(group, 458 - FANOTIFY_PE(kevent), FAN_DENY); 393 + FANOTIFY_PERM(event), FAN_DENY); 459 394 wake_up(&group->fanotify_data.access_waitq); 460 395 } else { 461 396 spin_lock(&group->notification_lock); 462 - list_add_tail(&kevent->list, 397 + list_add_tail(&event->fse.list, 463 398 &group->fanotify_data.access_list); 464 399 spin_unlock(&group->notification_lock); 465 400 } ··· 505 440 static int fanotify_release(struct inode *ignored, struct file *file) 506 441 { 507 442 struct fsnotify_group *group = file->private_data; 508 - struct fanotify_perm_event *event; 509 - struct fsnotify_event *fsn_event; 510 443 511 444 /* 512 445 * Stop new events from arriving in the notification queue. since ··· 519 456 */ 520 457 spin_lock(&group->notification_lock); 521 458 while (!list_empty(&group->fanotify_data.access_list)) { 459 + struct fanotify_perm_event *event; 460 + 522 461 event = list_first_entry(&group->fanotify_data.access_list, 523 462 struct fanotify_perm_event, fae.fse.list); 524 463 list_del_init(&event->fae.fse.list); ··· 534 469 * response is consumed and fanotify_get_response() returns. 535 470 */ 536 471 while (!fsnotify_notify_queue_is_empty(group)) { 537 - fsn_event = fsnotify_remove_first_event(group); 538 - if (!(FANOTIFY_E(fsn_event)->mask & FANOTIFY_PERM_EVENTS)) { 472 + struct fanotify_event *event; 473 + 474 + event = FANOTIFY_E(fsnotify_remove_first_event(group)); 475 + if (!(event->mask & FANOTIFY_PERM_EVENTS)) { 539 476 spin_unlock(&group->notification_lock); 540 - fsnotify_destroy_event(group, fsn_event); 477 + fsnotify_destroy_event(group, &event->fse); 541 478 } else { 542 - finish_permission_event(group, FANOTIFY_PE(fsn_event), 479 + finish_permission_event(group, FANOTIFY_PERM(event), 543 480 FAN_ALLOW); 544 481 } 545 482 spin_lock(&group->notification_lock); ··· 891 824 group->memcg = get_mem_cgroup_from_mm(current->mm); 892 825 893 826 oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, 894 - FSNOTIFY_EVENT_NONE, NULL); 827 + FSNOTIFY_EVENT_NONE, NULL, NULL); 895 828 if (unlikely(!oevent)) { 896 829 fd = -ENOMEM; 897 830 goto out_destroy_group; ··· 1206 1139 1207 1140 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark, 1208 1141 SLAB_PANIC|SLAB_ACCOUNT); 1209 - fanotify_event_cachep = KMEM_CACHE(fanotify_event, SLAB_PANIC); 1142 + fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event, 1143 + SLAB_PANIC); 1144 + fanotify_path_event_cachep = KMEM_CACHE(fanotify_path_event, 1145 + SLAB_PANIC); 1210 1146 if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) { 1211 1147 fanotify_perm_event_cachep = 1212 1148 KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
+8 -14
fs/notify/fsnotify.c
··· 143 143 } 144 144 145 145 /* Notify this dentry's parent about a child's events. */ 146 - int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask) 146 + int fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, 147 + int data_type) 147 148 { 148 149 struct dentry *parent; 149 150 struct inode *p_inode; 150 151 int ret = 0; 151 - 152 - if (!dentry) 153 - dentry = path->dentry; 154 152 155 153 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) 156 154 return 0; ··· 166 168 mask |= FS_EVENT_ON_CHILD; 167 169 168 170 take_dentry_name_snapshot(&name, dentry); 169 - if (path) 170 - ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, 171 - &name.name, 0); 172 - else 173 - ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, 174 - &name.name, 0); 171 + ret = fsnotify(p_inode, mask, data, data_type, &name.name, 0); 175 172 release_dentry_name_snapshot(&name); 176 173 } 177 174 ··· 174 181 175 182 return ret; 176 183 } 177 - EXPORT_SYMBOL_GPL(__fsnotify_parent); 184 + EXPORT_SYMBOL_GPL(fsnotify_parent); 178 185 179 186 static int send_to_group(struct inode *to_tell, 180 187 __u32 mask, const void *data, ··· 311 318 int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, 312 319 const struct qstr *file_name, u32 cookie) 313 320 { 321 + const struct path *path = fsnotify_data_path(data, data_is); 314 322 struct fsnotify_iter_info iter_info = {}; 315 323 struct super_block *sb = to_tell->i_sb; 316 324 struct mount *mnt = NULL; ··· 319 325 int ret = 0; 320 326 __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS); 321 327 322 - if (data_is == FSNOTIFY_EVENT_PATH) { 323 - mnt = real_mount(((const struct path *)data)->mnt); 328 + if (path) { 329 + mnt = real_mount(path->mnt); 324 330 mnt_or_sb_mask |= mnt->mnt_fsnotify_mask; 325 331 } 326 332 /* An event "on child" is not intended for a mount/sb mark */ ··· 383 389 { 384 390 int ret; 385 391 386 - BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 25); 392 + BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 26); 387 393 388 394 ret = init_srcu_struct(&fsnotify_mark_srcu); 389 395 if (ret)
+5 -7
fs/notify/inotify/inotify_fsnotify.c
··· 39 39 if (old->mask & FS_IN_IGNORED) 40 40 return false; 41 41 if ((old->mask == new->mask) && 42 - (old_fsn->inode == new_fsn->inode) && 42 + (old_fsn->objectid == new_fsn->objectid) && 43 43 (old->name_len == new->name_len) && 44 44 (!old->name_len || !strcmp(old->name, new->name))) 45 45 return true; ··· 61 61 const struct qstr *file_name, u32 cookie, 62 62 struct fsnotify_iter_info *iter_info) 63 63 { 64 + const struct path *path = fsnotify_data_path(data, data_type); 64 65 struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); 65 66 struct inotify_inode_mark *i_mark; 66 67 struct inotify_event_info *event; ··· 74 73 return 0; 75 74 76 75 if ((inode_mark->mask & FS_EXCL_UNLINK) && 77 - (data_type == FSNOTIFY_EVENT_PATH)) { 78 - const struct path *path = data; 76 + path && d_unlinked(path->dentry)) 77 + return 0; 79 78 80 - if (d_unlinked(path->dentry)) 81 - return 0; 82 - } 83 79 if (file_name) { 84 80 len = file_name->len; 85 81 alloc_len += len + 1; ··· 116 118 mask &= ~IN_ISDIR; 117 119 118 120 fsn_event = &event->fse; 119 - fsnotify_init_event(fsn_event, inode); 121 + fsnotify_init_event(fsn_event, (unsigned long)inode); 120 122 event->mask = mask; 121 123 event->wd = i_mark->wd; 122 124 event->sync_cookie = cookie;
+1 -1
fs/notify/inotify/inotify_user.c
··· 635 635 return ERR_PTR(-ENOMEM); 636 636 } 637 637 group->overflow_event = &oevent->fse; 638 - fsnotify_init_event(group->overflow_event, NULL); 638 + fsnotify_init_event(group->overflow_event, 0); 639 639 oevent->mask = FS_Q_OVERFLOW; 640 640 oevent->wd = -1; 641 641 oevent->sync_cookie = 0;
+2 -1
include/linux/fanotify.h
··· 47 47 * Directory entry modification events - reported only to directory 48 48 * where entry is modified and not to a watching parent. 49 49 */ 50 - #define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE) 50 + #define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE | \ 51 + FAN_DIR_MODIFY) 51 52 52 53 /* Events that can only be reported with data type FSNOTIFY_EVENT_INODE */ 53 54 #define FANOTIFY_INODE_EVENTS (FANOTIFY_DIRENT_EVENTS | \
+58 -80
include/linux/fsnotify.h
··· 18 18 #include <linux/bug.h> 19 19 20 20 /* 21 - * Notify this @dir inode about a change in the directory entry @dentry. 21 + * Notify this @dir inode about a change in a child directory entry. 22 + * The directory entry may have turned positive or negative or its inode may 23 + * have changed (i.e. renamed over). 22 24 * 23 25 * Unlike fsnotify_parent(), the event will be reported regardless of the 24 26 * FS_EVENT_ON_CHILD mask on the parent inode. 25 27 */ 26 - static inline int fsnotify_dirent(struct inode *dir, struct dentry *dentry, 27 - __u32 mask) 28 + static inline void fsnotify_name(struct inode *dir, __u32 mask, 29 + struct inode *child, 30 + const struct qstr *name, u32 cookie) 28 31 { 29 - return fsnotify(dir, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE, 30 - &dentry->d_name, 0); 32 + fsnotify(dir, mask, child, FSNOTIFY_EVENT_INODE, name, cookie); 33 + /* 34 + * Send another flavor of the event without child inode data and 35 + * without the specific event type (e.g. FS_CREATE|FS_IS_DIR). 36 + * The name is relative to the dir inode the event is reported to. 37 + */ 38 + fsnotify(dir, FS_DIR_MODIFY, dir, FSNOTIFY_EVENT_INODE, name, 0); 31 39 } 32 40 33 - /* Notify this dentry's parent about a child's events. */ 34 - static inline int fsnotify_parent(const struct path *path, 35 - struct dentry *dentry, __u32 mask) 41 + static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, 42 + __u32 mask) 36 43 { 37 - if (!dentry) 38 - dentry = path->dentry; 39 - 40 - return __fsnotify_parent(path, dentry, mask); 44 + fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0); 41 45 } 42 46 43 47 /* 44 - * Simple wrapper to consolidate calls fsnotify_parent()/fsnotify() when 45 - * an event is on a path. 48 + * Simple wrappers to consolidate calls fsnotify_parent()/fsnotify() when 49 + * an event is on a file/dentry. 46 50 */ 47 - static inline int fsnotify_path(struct inode *inode, const struct path *path, 48 - __u32 mask) 51 + static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask) 49 52 { 50 - int ret = fsnotify_parent(path, NULL, mask); 53 + struct inode *inode = d_inode(dentry); 51 54 55 + if (S_ISDIR(inode->i_mode)) 56 + mask |= FS_ISDIR; 57 + 58 + fsnotify_parent(dentry, mask, inode, FSNOTIFY_EVENT_INODE); 59 + fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 60 + } 61 + 62 + static inline int fsnotify_file(struct file *file, __u32 mask) 63 + { 64 + const struct path *path = &file->f_path; 65 + struct inode *inode = file_inode(file); 66 + int ret; 67 + 68 + if (file->f_mode & FMODE_NONOTIFY) 69 + return 0; 70 + 71 + if (S_ISDIR(inode->i_mode)) 72 + mask |= FS_ISDIR; 73 + 74 + ret = fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); 52 75 if (ret) 53 76 return ret; 77 + 54 78 return fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 55 79 } 56 80 ··· 82 58 static inline int fsnotify_perm(struct file *file, int mask) 83 59 { 84 60 int ret; 85 - const struct path *path = &file->f_path; 86 - struct inode *inode = file_inode(file); 87 61 __u32 fsnotify_mask = 0; 88 62 89 - if (file->f_mode & FMODE_NONOTIFY) 90 - return 0; 91 63 if (!(mask & (MAY_READ | MAY_OPEN))) 92 64 return 0; 65 + 93 66 if (mask & MAY_OPEN) { 94 67 fsnotify_mask = FS_OPEN_PERM; 95 68 96 69 if (file->f_flags & __FMODE_EXEC) { 97 - ret = fsnotify_path(inode, path, FS_OPEN_EXEC_PERM); 70 + ret = fsnotify_file(file, FS_OPEN_EXEC_PERM); 98 71 99 72 if (ret) 100 73 return ret; ··· 100 79 fsnotify_mask = FS_ACCESS_PERM; 101 80 } 102 81 103 - if (S_ISDIR(inode->i_mode)) 104 - fsnotify_mask |= FS_ISDIR; 105 - 106 - return fsnotify_path(inode, path, fsnotify_mask); 82 + return fsnotify_file(file, fsnotify_mask); 107 83 } 108 84 109 85 /* ··· 140 122 mask |= FS_ISDIR; 141 123 } 142 124 143 - fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name, 144 - fs_cookie); 145 - fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name, 146 - fs_cookie); 125 + fsnotify_name(old_dir, old_dir_mask, source, old_name, fs_cookie); 126 + fsnotify_name(new_dir, new_dir_mask, source, new_name, fs_cookie); 147 127 148 128 if (target) 149 129 fsnotify_link_count(target); ··· 196 180 * Note: We have to pass also the linked inode ptr as some filesystems leave 197 181 * new_dentry->d_inode NULL and instantiate inode pointer later 198 182 */ 199 - static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) 183 + static inline void fsnotify_link(struct inode *dir, struct inode *inode, 184 + struct dentry *new_dentry) 200 185 { 201 186 fsnotify_link_count(inode); 202 187 audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE); 203 188 204 - fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, &new_dentry->d_name, 0); 189 + fsnotify_name(dir, FS_CREATE, inode, &new_dentry->d_name, 0); 205 190 } 206 191 207 192 /* ··· 246 229 */ 247 230 static inline void fsnotify_access(struct file *file) 248 231 { 249 - const struct path *path = &file->f_path; 250 - struct inode *inode = file_inode(file); 251 - __u32 mask = FS_ACCESS; 252 - 253 - if (S_ISDIR(inode->i_mode)) 254 - mask |= FS_ISDIR; 255 - 256 - if (!(file->f_mode & FMODE_NONOTIFY)) 257 - fsnotify_path(inode, path, mask); 232 + fsnotify_file(file, FS_ACCESS); 258 233 } 259 234 260 235 /* ··· 254 245 */ 255 246 static inline void fsnotify_modify(struct file *file) 256 247 { 257 - const struct path *path = &file->f_path; 258 - struct inode *inode = file_inode(file); 259 - __u32 mask = FS_MODIFY; 260 - 261 - if (S_ISDIR(inode->i_mode)) 262 - mask |= FS_ISDIR; 263 - 264 - if (!(file->f_mode & FMODE_NONOTIFY)) 265 - fsnotify_path(inode, path, mask); 248 + fsnotify_file(file, FS_MODIFY); 266 249 } 267 250 268 251 /* ··· 262 261 */ 263 262 static inline void fsnotify_open(struct file *file) 264 263 { 265 - const struct path *path = &file->f_path; 266 - struct inode *inode = file_inode(file); 267 264 __u32 mask = FS_OPEN; 268 265 269 - if (S_ISDIR(inode->i_mode)) 270 - mask |= FS_ISDIR; 271 266 if (file->f_flags & __FMODE_EXEC) 272 267 mask |= FS_OPEN_EXEC; 273 268 274 - fsnotify_path(inode, path, mask); 269 + fsnotify_file(file, mask); 275 270 } 276 271 277 272 /* ··· 275 278 */ 276 279 static inline void fsnotify_close(struct file *file) 277 280 { 278 - const struct path *path = &file->f_path; 279 - struct inode *inode = file_inode(file); 280 - fmode_t mode = file->f_mode; 281 - __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; 281 + __u32 mask = (file->f_mode & FMODE_WRITE) ? FS_CLOSE_WRITE : 282 + FS_CLOSE_NOWRITE; 282 283 283 - if (S_ISDIR(inode->i_mode)) 284 - mask |= FS_ISDIR; 285 - 286 - if (!(file->f_mode & FMODE_NONOTIFY)) 287 - fsnotify_path(inode, path, mask); 284 + fsnotify_file(file, mask); 288 285 } 289 286 290 287 /* ··· 286 295 */ 287 296 static inline void fsnotify_xattr(struct dentry *dentry) 288 297 { 289 - struct inode *inode = dentry->d_inode; 290 - __u32 mask = FS_ATTRIB; 291 - 292 - if (S_ISDIR(inode->i_mode)) 293 - mask |= FS_ISDIR; 294 - 295 - fsnotify_parent(NULL, dentry, mask); 296 - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 298 + fsnotify_dentry(dentry, FS_ATTRIB); 297 299 } 298 300 299 301 /* ··· 295 311 */ 296 312 static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) 297 313 { 298 - struct inode *inode = dentry->d_inode; 299 314 __u32 mask = 0; 300 315 301 316 if (ia_valid & ATTR_UID) ··· 315 332 if (ia_valid & ATTR_MODE) 316 333 mask |= FS_ATTRIB; 317 334 318 - if (mask) { 319 - if (S_ISDIR(inode->i_mode)) 320 - mask |= FS_ISDIR; 321 - 322 - fsnotify_parent(NULL, dentry, mask); 323 - fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 324 - } 335 + if (mask) 336 + fsnotify_dentry(dentry, mask); 325 337 } 326 338 327 339 #endif /* _LINUX_FS_NOTIFY_H */
+49 -21
include/linux/fsnotify_backend.h
··· 47 47 #define FS_OPEN_PERM 0x00010000 /* open event in an permission hook */ 48 48 #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ 49 49 #define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */ 50 + #define FS_DIR_MODIFY 0x00080000 /* Directory entry was modified */ 50 51 51 52 #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ 52 - #define FS_ISDIR 0x40000000 /* event occurred against dir */ 53 - #define FS_IN_ONESHOT 0x80000000 /* only send event once */ 54 - 55 - #define FS_DN_RENAME 0x10000000 /* file renamed */ 56 - #define FS_DN_MULTISHOT 0x20000000 /* dnotify multishot */ 57 - 58 53 /* This inode cares about things that happen to its children. Always set for 59 54 * dnotify and inotify. */ 60 55 #define FS_EVENT_ON_CHILD 0x08000000 56 + 57 + #define FS_DN_RENAME 0x10000000 /* file renamed */ 58 + #define FS_DN_MULTISHOT 0x20000000 /* dnotify multishot */ 59 + #define FS_ISDIR 0x40000000 /* event occurred against dir */ 60 + #define FS_IN_ONESHOT 0x80000000 /* only send event once */ 61 61 62 62 #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) 63 63 ··· 67 67 * The watching parent may get an FS_ATTRIB|FS_EVENT_ON_CHILD event 68 68 * when a directory entry inside a child subdir changes. 69 69 */ 70 - #define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE) 70 + #define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | \ 71 + FS_DIR_MODIFY) 71 72 72 73 #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \ 73 74 FS_OPEN_EXEC_PERM) ··· 134 133 */ 135 134 struct fsnotify_event { 136 135 struct list_head list; 137 - /* inode may ONLY be dereferenced during handle_event(). */ 138 - struct inode *inode; /* either the inode the event happened to or its parent */ 136 + unsigned long objectid; /* identifier for queue merges */ 139 137 }; 140 138 141 139 /* ··· 213 213 }; 214 214 }; 215 215 216 - /* when calling fsnotify tell it if the data is a path or inode */ 217 - #define FSNOTIFY_EVENT_NONE 0 218 - #define FSNOTIFY_EVENT_PATH 1 219 - #define FSNOTIFY_EVENT_INODE 2 216 + /* When calling fsnotify tell it if the data is a path or inode */ 217 + enum fsnotify_data_type { 218 + FSNOTIFY_EVENT_NONE, 219 + FSNOTIFY_EVENT_PATH, 220 + FSNOTIFY_EVENT_INODE, 221 + }; 222 + 223 + static inline const struct inode *fsnotify_data_inode(const void *data, 224 + int data_type) 225 + { 226 + switch (data_type) { 227 + case FSNOTIFY_EVENT_INODE: 228 + return data; 229 + case FSNOTIFY_EVENT_PATH: 230 + return d_inode(((const struct path *)data)->dentry); 231 + default: 232 + return NULL; 233 + } 234 + } 235 + 236 + static inline const struct path *fsnotify_data_path(const void *data, 237 + int data_type) 238 + { 239 + switch (data_type) { 240 + case FSNOTIFY_EVENT_PATH: 241 + return data; 242 + default: 243 + return NULL; 244 + } 245 + } 220 246 221 247 enum fsnotify_obj_type { 222 248 FSNOTIFY_OBJ_TYPE_INODE, ··· 377 351 /* called from the vfs helpers */ 378 352 379 353 /* main fsnotify call to send events */ 380 - extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, 381 - const struct qstr *name, u32 cookie); 382 - extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask); 354 + extern int fsnotify(struct inode *to_tell, __u32 mask, const void *data, 355 + int data_type, const struct qstr *name, u32 cookie); 356 + extern int fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, 357 + int data_type); 383 358 extern void __fsnotify_inode_delete(struct inode *inode); 384 359 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); 385 360 extern void fsnotify_sb_delete(struct super_block *sb); ··· 527 500 extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info); 528 501 529 502 static inline void fsnotify_init_event(struct fsnotify_event *event, 530 - struct inode *inode) 503 + unsigned long objectid) 531 504 { 532 505 INIT_LIST_HEAD(&event->list); 533 - event->inode = inode; 506 + event->objectid = objectid; 534 507 } 535 508 536 509 #else 537 510 538 - static inline int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is, 539 - const struct qstr *name, u32 cookie) 511 + static inline int fsnotify(struct inode *to_tell, __u32 mask, const void *data, 512 + int data_type, const struct qstr *name, u32 cookie) 540 513 { 541 514 return 0; 542 515 } 543 516 544 - static inline int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask) 517 + static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, 518 + const void *data, int data_type) 545 519 { 546 520 return 0; 547 521 }
+10 -3
include/uapi/linux/fanotify.h
··· 24 24 #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ 25 25 #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ 26 26 #define FAN_OPEN_EXEC_PERM 0x00040000 /* File open/exec in perm check */ 27 + #define FAN_DIR_MODIFY 0x00080000 /* Directory entry was modified */ 27 28 28 - #define FAN_ONDIR 0x40000000 /* event occurred against dir */ 29 + #define FAN_EVENT_ON_CHILD 0x08000000 /* Interested in child events */ 29 30 30 - #define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ 31 + #define FAN_ONDIR 0x40000000 /* Event occurred against dir */ 31 32 32 33 /* helper events */ 33 34 #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ ··· 117 116 }; 118 117 119 118 #define FAN_EVENT_INFO_TYPE_FID 1 119 + #define FAN_EVENT_INFO_TYPE_DFID_NAME 2 120 120 121 121 /* Variable length info record following event metadata */ 122 122 struct fanotify_event_info_header { ··· 126 124 __u16 len; 127 125 }; 128 126 129 - /* Unique file identifier info record */ 127 + /* 128 + * Unique file identifier info record. This is used both for 129 + * FAN_EVENT_INFO_TYPE_FID records and for FAN_EVENT_INFO_TYPE_DFID_NAME 130 + * records. For FAN_EVENT_INFO_TYPE_DFID_NAME there is additionally a null 131 + * terminated name immediately after the file handle. 132 + */ 130 133 struct fanotify_event_info_fid { 131 134 struct fanotify_event_info_header hdr; 132 135 __kernel_fsid_t fsid;
+2 -11
kernel/audit_fsnotify.c
··· 160 160 { 161 161 struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); 162 162 struct audit_fsnotify_mark *audit_mark; 163 - const struct inode *inode = NULL; 163 + const struct inode *inode = fsnotify_data_inode(data, data_type); 164 164 165 165 audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark); 166 166 167 167 BUG_ON(group != audit_fsnotify_group); 168 168 169 - switch (data_type) { 170 - case (FSNOTIFY_EVENT_PATH): 171 - inode = ((const struct path *)data)->dentry->d_inode; 172 - break; 173 - case (FSNOTIFY_EVENT_INODE): 174 - inode = (const struct inode *)data; 175 - break; 176 - default: 177 - BUG(); 169 + if (WARN_ON(!inode)) 178 170 return 0; 179 - } 180 171 181 172 if (mask & (FS_CREATE|FS_MOVED_TO|FS_DELETE|FS_MOVED_FROM)) { 182 173 if (audit_compare_dname_path(dname, audit_mark->path, AUDIT_NAME_FULL))
+2 -14
kernel/audit_watch.c
··· 471 471 struct fsnotify_iter_info *iter_info) 472 472 { 473 473 struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); 474 - const struct inode *inode; 474 + const struct inode *inode = fsnotify_data_inode(data, data_type); 475 475 struct audit_parent *parent; 476 476 477 477 parent = container_of(inode_mark, struct audit_parent, mark); 478 478 479 479 BUG_ON(group != audit_watch_group); 480 - 481 - switch (data_type) { 482 - case (FSNOTIFY_EVENT_PATH): 483 - inode = d_backing_inode(((const struct path *)data)->dentry); 484 - break; 485 - case (FSNOTIFY_EVENT_INODE): 486 - inode = (const struct inode *)data; 487 - break; 488 - default: 489 - BUG(); 490 - inode = NULL; 491 - break; 492 - } 480 + WARN_ON(!inode); 493 481 494 482 if (mask & (FS_CREATE|FS_MOVED_TO) && inode) 495 483 audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);