diff options
Diffstat (limited to 'fs/notify/fanotify')
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 6 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 37 |
2 files changed, 31 insertions, 12 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index a50636025364..0c2f9122b262 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -18,6 +18,12 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) | |||
18 | old->tgid == new->tgid) { | 18 | old->tgid == new->tgid) { |
19 | switch (old->data_type) { | 19 | switch (old->data_type) { |
20 | case (FSNOTIFY_EVENT_PATH): | 20 | case (FSNOTIFY_EVENT_PATH): |
21 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | ||
22 | /* dont merge two permission events */ | ||
23 | if ((old->mask & FAN_ALL_PERM_EVENTS) && | ||
24 | (new->mask & FAN_ALL_PERM_EVENTS)) | ||
25 | return false; | ||
26 | #endif | ||
21 | if ((old->path.mnt == new->path.mnt) && | 27 | if ((old->path.mnt == new->path.mnt) && |
22 | (old->path.dentry == new->path.dentry)) | 28 | (old->path.dentry == new->path.dentry)) |
23 | return true; | 29 | return true; |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index a5cd9bba022f..9ff4a5ee6e20 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -397,8 +397,12 @@ static int fanotify_release(struct inode *ignored, struct file *file) | |||
397 | 397 | ||
398 | wake_up(&group->fanotify_data.access_waitq); | 398 | wake_up(&group->fanotify_data.access_waitq); |
399 | #endif | 399 | #endif |
400 | |||
401 | if (file->f_flags & FASYNC) | ||
402 | fsnotify_fasync(-1, file, 0); | ||
403 | |||
400 | /* matches the fanotify_init->fsnotify_alloc_group */ | 404 | /* matches the fanotify_init->fsnotify_alloc_group */ |
401 | fsnotify_put_group(group); | 405 | fsnotify_destroy_group(group); |
402 | 406 | ||
403 | return 0; | 407 | return 0; |
404 | } | 408 | } |
@@ -493,7 +497,8 @@ out: | |||
493 | 497 | ||
494 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, | 498 | static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, |
495 | __u32 mask, | 499 | __u32 mask, |
496 | unsigned int flags) | 500 | unsigned int flags, |
501 | int *destroy) | ||
497 | { | 502 | { |
498 | __u32 oldmask; | 503 | __u32 oldmask; |
499 | 504 | ||
@@ -507,8 +512,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, | |||
507 | } | 512 | } |
508 | spin_unlock(&fsn_mark->lock); | 513 | spin_unlock(&fsn_mark->lock); |
509 | 514 | ||
510 | if (!(oldmask & ~mask)) | 515 | *destroy = !(oldmask & ~mask); |
511 | fsnotify_destroy_mark(fsn_mark); | ||
512 | 516 | ||
513 | return mask & oldmask; | 517 | return mask & oldmask; |
514 | } | 518 | } |
@@ -519,12 +523,17 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group, | |||
519 | { | 523 | { |
520 | struct fsnotify_mark *fsn_mark = NULL; | 524 | struct fsnotify_mark *fsn_mark = NULL; |
521 | __u32 removed; | 525 | __u32 removed; |
526 | int destroy_mark; | ||
522 | 527 | ||
523 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); | 528 | fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); |
524 | if (!fsn_mark) | 529 | if (!fsn_mark) |
525 | return -ENOENT; | 530 | return -ENOENT; |
526 | 531 | ||
527 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); | 532 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, |
533 | &destroy_mark); | ||
534 | if (destroy_mark) | ||
535 | fsnotify_destroy_mark(fsn_mark, group); | ||
536 | |||
528 | fsnotify_put_mark(fsn_mark); | 537 | fsnotify_put_mark(fsn_mark); |
529 | if (removed & real_mount(mnt)->mnt_fsnotify_mask) | 538 | if (removed & real_mount(mnt)->mnt_fsnotify_mask) |
530 | fsnotify_recalc_vfsmount_mask(mnt); | 539 | fsnotify_recalc_vfsmount_mask(mnt); |
@@ -538,12 +547,16 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, | |||
538 | { | 547 | { |
539 | struct fsnotify_mark *fsn_mark = NULL; | 548 | struct fsnotify_mark *fsn_mark = NULL; |
540 | __u32 removed; | 549 | __u32 removed; |
550 | int destroy_mark; | ||
541 | 551 | ||
542 | fsn_mark = fsnotify_find_inode_mark(group, inode); | 552 | fsn_mark = fsnotify_find_inode_mark(group, inode); |
543 | if (!fsn_mark) | 553 | if (!fsn_mark) |
544 | return -ENOENT; | 554 | return -ENOENT; |
545 | 555 | ||
546 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags); | 556 | removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags, |
557 | &destroy_mark); | ||
558 | if (destroy_mark) | ||
559 | fsnotify_destroy_mark(fsn_mark, group); | ||
547 | /* matches the fsnotify_find_inode_mark() */ | 560 | /* matches the fsnotify_find_inode_mark() */ |
548 | fsnotify_put_mark(fsn_mark); | 561 | fsnotify_put_mark(fsn_mark); |
549 | if (removed & inode->i_fsnotify_mask) | 562 | if (removed & inode->i_fsnotify_mask) |
@@ -710,13 +723,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
710 | break; | 723 | break; |
711 | default: | 724 | default: |
712 | fd = -EINVAL; | 725 | fd = -EINVAL; |
713 | goto out_put_group; | 726 | goto out_destroy_group; |
714 | } | 727 | } |
715 | 728 | ||
716 | if (flags & FAN_UNLIMITED_QUEUE) { | 729 | if (flags & FAN_UNLIMITED_QUEUE) { |
717 | fd = -EPERM; | 730 | fd = -EPERM; |
718 | if (!capable(CAP_SYS_ADMIN)) | 731 | if (!capable(CAP_SYS_ADMIN)) |
719 | goto out_put_group; | 732 | goto out_destroy_group; |
720 | group->max_events = UINT_MAX; | 733 | group->max_events = UINT_MAX; |
721 | } else { | 734 | } else { |
722 | group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS; | 735 | group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS; |
@@ -725,7 +738,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
725 | if (flags & FAN_UNLIMITED_MARKS) { | 738 | if (flags & FAN_UNLIMITED_MARKS) { |
726 | fd = -EPERM; | 739 | fd = -EPERM; |
727 | if (!capable(CAP_SYS_ADMIN)) | 740 | if (!capable(CAP_SYS_ADMIN)) |
728 | goto out_put_group; | 741 | goto out_destroy_group; |
729 | group->fanotify_data.max_marks = UINT_MAX; | 742 | group->fanotify_data.max_marks = UINT_MAX; |
730 | } else { | 743 | } else { |
731 | group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS; | 744 | group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS; |
@@ -733,12 +746,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
733 | 746 | ||
734 | fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); | 747 | fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); |
735 | if (fd < 0) | 748 | if (fd < 0) |
736 | goto out_put_group; | 749 | goto out_destroy_group; |
737 | 750 | ||
738 | return fd; | 751 | return fd; |
739 | 752 | ||
740 | out_put_group: | 753 | out_destroy_group: |
741 | fsnotify_put_group(group); | 754 | fsnotify_destroy_group(group); |
742 | return fd; | 755 | return fd; |
743 | } | 756 | } |
744 | 757 | ||