aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fanotify
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/fanotify')
-rw-r--r--fs/notify/fanotify/fanotify.c6
-rw-r--r--fs/notify/fanotify/fanotify_user.c37
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
494static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, 498static __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
740out_put_group: 753out_destroy_group:
741 fsnotify_put_group(group); 754 fsnotify_destroy_group(group);
742 return fd; 755 return fd;
743} 756}
744 757