Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify

* 'for-linus' of git://git.infradead.org/users/eparis/notify: (22 commits)
Ensure FMODE_NONOTIFY is not set by userspace
make fanotify_read() restartable across signals
fsnotify: remove alignment padding from fsnotify_mark on 64 bit builds
fs/notify/fanotify/fanotify_user.c: fix warnings
fanotify: Fix FAN_CLOSE comments
fanotify: do not recalculate the mask if the ignored mask changed
fanotify: ignore events on directories unless specifically requested
fsnotify: rename FS_IN_ISDIR to FS_ISDIR
fanotify: do not send events for irregular files
fanotify: limit number of listeners per user
fanotify: allow userspace to override max marks
fanotify: limit the number of marks in a single fanotify group
fanotify: allow userspace to override max queue depth
fsnotify: implement a default maximum queue depth
fanotify: ignore fanotify ignore marks if open writers
fanotify: allow userspace to flush all marks
fsnotify: call fsnotify_parent in perm events
fsnotify: correctly handle return codes from listeners
fanotify: use __aligned_u64 in fanotify userspace metadata
fanotify: implement fanotify listener ordering
...

+219 -64
+1 -1
fs/notify/Kconfig
··· 3 3 4 4 source "fs/notify/dnotify/Kconfig" 5 5 source "fs/notify/inotify/Kconfig" 6 - #source "fs/notify/fanotify/Kconfig" 6 + source "fs/notify/fanotify/Kconfig"
+21 -6
fs/notify/fanotify/fanotify.c
··· 131 131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW); 132 132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM); 133 133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); 134 + BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR); 134 135 135 136 pr_debug("%s: group=%p event=%p\n", __func__, group, event); 136 137 ··· 161 160 __u32 event_mask, void *data, int data_type) 162 161 { 163 162 __u32 marks_mask, marks_ignored_mask; 163 + struct path *path = data; 164 164 165 165 pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p " 166 166 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell, 167 167 inode_mark, vfsmnt_mark, event_mask, data, data_type); 168 168 169 - /* sorry, fanotify only gives a damn about files and dirs */ 170 - if (!S_ISREG(to_tell->i_mode) && 171 - !S_ISDIR(to_tell->i_mode)) 172 - return false; 173 - 174 169 /* if we don't have enough info to send an event to userspace say no */ 175 170 if (data_type != FSNOTIFY_EVENT_PATH) 171 + return false; 172 + 173 + /* sorry, fanotify only gives a damn about files and dirs */ 174 + if (!S_ISREG(path->dentry->d_inode->i_mode) && 175 + !S_ISDIR(path->dentry->d_inode->i_mode)) 176 176 return false; 177 177 178 178 if (inode_mark && vfsmnt_mark) { ··· 196 194 BUG(); 197 195 } 198 196 197 + if (S_ISDIR(path->dentry->d_inode->i_mode) && 198 + (marks_ignored_mask & FS_ISDIR)) 199 + return false; 200 + 199 201 if (event_mask & marks_mask & ~marks_ignored_mask) 200 202 return true; 201 203 202 204 return false; 203 205 } 204 206 207 + static void fanotify_free_group_priv(struct fsnotify_group *group) 208 + { 209 + struct user_struct *user; 210 + 211 + user = group->fanotify_data.user; 212 + atomic_dec(&user->fanotify_listeners); 213 + free_uid(user); 214 + } 215 + 205 216 const struct fsnotify_ops fanotify_fsnotify_ops = { 206 217 .handle_event = fanotify_handle_event, 207 218 .should_send_event = fanotify_should_send_event, 208 - .free_group_priv = NULL, 219 + .free_group_priv = fanotify_free_group_priv, 209 220 .free_event_priv = NULL, 210 221 .freeing_mark = NULL, 211 222 };
+90 -8
fs/notify/fanotify/fanotify_user.c
··· 16 16 17 17 #include <asm/ioctls.h> 18 18 19 + #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 20 + #define FANOTIFY_DEFAULT_MAX_MARKS 8192 21 + #define FANOTIFY_DEFAULT_MAX_LISTENERS 128 22 + 19 23 extern const struct fsnotify_ops fanotify_fsnotify_ops; 20 24 21 25 static struct kmem_cache *fanotify_mark_cache __read_mostly; ··· 330 326 ret = -EAGAIN; 331 327 if (file->f_flags & O_NONBLOCK) 332 328 break; 333 - ret = -EINTR; 329 + ret = -ERESTARTSYS; 334 330 if (signal_pending(current)) 335 331 break; 336 332 ··· 376 372 static int fanotify_release(struct inode *ignored, struct file *file) 377 373 { 378 374 struct fsnotify_group *group = file->private_data; 379 - struct fanotify_response_event *re, *lre; 380 - 381 - pr_debug("%s: file=%p group=%p\n", __func__, file, group); 382 375 383 376 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 377 + struct fanotify_response_event *re, *lre; 378 + 384 379 mutex_lock(&group->fanotify_data.access_mutex); 385 380 386 381 group->fanotify_data.bypass_perm = true; ··· 557 554 __u32 mask, 558 555 unsigned int flags) 559 556 { 560 - __u32 oldmask; 557 + __u32 oldmask = -1; 561 558 562 559 spin_lock(&fsn_mark->lock); 563 560 if (!(flags & FAN_MARK_IGNORED_MASK)) { 564 561 oldmask = fsn_mark->mask; 565 562 fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask)); 566 563 } else { 567 - oldmask = fsn_mark->ignored_mask; 568 - fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask | mask)); 564 + __u32 tmask = fsn_mark->ignored_mask | mask; 565 + fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask); 569 566 if (flags & FAN_MARK_IGNORED_SURV_MODIFY) 570 567 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; 571 568 } 569 + 570 + if (!(flags & FAN_MARK_ONDIR)) { 571 + __u32 tmask = fsn_mark->ignored_mask | FAN_ONDIR; 572 + fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask); 573 + } 574 + 572 575 spin_unlock(&fsn_mark->lock); 573 576 574 577 return mask & ~oldmask; ··· 590 581 fsn_mark = fsnotify_find_vfsmount_mark(group, mnt); 591 582 if (!fsn_mark) { 592 583 int ret; 584 + 585 + if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks) 586 + return -ENOSPC; 593 587 594 588 fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); 595 589 if (!fsn_mark) ··· 622 610 623 611 pr_debug("%s: group=%p inode=%p\n", __func__, group, inode); 624 612 613 + /* 614 + * If some other task has this inode open for write we should not add 615 + * an ignored mark, unless that ignored mark is supposed to survive 616 + * modification changes anyway. 617 + */ 618 + if ((flags & FAN_MARK_IGNORED_MASK) && 619 + !(flags & FAN_MARK_IGNORED_SURV_MODIFY) && 620 + (atomic_read(&inode->i_writecount) > 0)) 621 + return 0; 622 + 625 623 fsn_mark = fsnotify_find_inode_mark(group, inode); 626 624 if (!fsn_mark) { 627 625 int ret; 626 + 627 + if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks) 628 + return -ENOSPC; 628 629 629 630 fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL); 630 631 if (!fsn_mark) ··· 662 637 { 663 638 struct fsnotify_group *group; 664 639 int f_flags, fd; 640 + struct user_struct *user; 665 641 666 642 pr_debug("%s: flags=%d event_f_flags=%d\n", 667 643 __func__, flags, event_f_flags); ··· 672 646 673 647 if (flags & ~FAN_ALL_INIT_FLAGS) 674 648 return -EINVAL; 649 + 650 + user = get_current_user(); 651 + if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) { 652 + free_uid(user); 653 + return -EMFILE; 654 + } 675 655 676 656 f_flags = O_RDWR | FMODE_NONOTIFY; 677 657 if (flags & FAN_CLOEXEC) ··· 690 658 if (IS_ERR(group)) 691 659 return PTR_ERR(group); 692 660 661 + group->fanotify_data.user = user; 662 + atomic_inc(&user->fanotify_listeners); 663 + 693 664 group->fanotify_data.f_flags = event_f_flags; 694 665 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 695 666 mutex_init(&group->fanotify_data.access_mutex); 696 667 init_waitqueue_head(&group->fanotify_data.access_waitq); 697 668 INIT_LIST_HEAD(&group->fanotify_data.access_list); 698 669 #endif 670 + switch (flags & FAN_ALL_CLASS_BITS) { 671 + case FAN_CLASS_NOTIF: 672 + group->priority = FS_PRIO_0; 673 + break; 674 + case FAN_CLASS_CONTENT: 675 + group->priority = FS_PRIO_1; 676 + break; 677 + case FAN_CLASS_PRE_CONTENT: 678 + group->priority = FS_PRIO_2; 679 + break; 680 + default: 681 + fd = -EINVAL; 682 + goto out_put_group; 683 + } 684 + 685 + if (flags & FAN_UNLIMITED_QUEUE) { 686 + fd = -EPERM; 687 + if (!capable(CAP_SYS_ADMIN)) 688 + goto out_put_group; 689 + group->max_events = UINT_MAX; 690 + } else { 691 + group->max_events = FANOTIFY_DEFAULT_MAX_EVENTS; 692 + } 693 + 694 + if (flags & FAN_UNLIMITED_MARKS) { 695 + fd = -EPERM; 696 + if (!capable(CAP_SYS_ADMIN)) 697 + goto out_put_group; 698 + group->fanotify_data.max_marks = UINT_MAX; 699 + } else { 700 + group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS; 701 + } 699 702 700 703 fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); 701 704 if (fd < 0) ··· 771 704 default: 772 705 return -EINVAL; 773 706 } 707 + 708 + if (mask & FAN_ONDIR) { 709 + flags |= FAN_MARK_ONDIR; 710 + mask &= ~FAN_ONDIR; 711 + } 712 + 774 713 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS 775 714 if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD)) 776 715 #else ··· 792 719 ret = -EINVAL; 793 720 if (unlikely(filp->f_op != &fanotify_fops)) 794 721 goto fput_and_out; 722 + group = filp->private_data; 723 + 724 + /* 725 + * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not 726 + * allowed to set permissions events. 727 + */ 728 + ret = -EINVAL; 729 + if (mask & FAN_ALL_PERM_EVENTS && 730 + group->priority == FS_PRIO_0) 731 + goto fput_and_out; 795 732 796 733 ret = fanotify_find_path(dfd, pathname, &path, flags); 797 734 if (ret) ··· 812 729 inode = path.dentry->d_inode; 813 730 else 814 731 mnt = path.mnt; 815 - group = filp->private_data; 816 732 817 733 /* create/update an inode mark */ 818 734 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
+21 -14
fs/notify/fsnotify.c
··· 84 84 } 85 85 86 86 /* Notify this dentry's parent about a child's events. */ 87 - void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 87 + int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 88 88 { 89 89 struct dentry *parent; 90 90 struct inode *p_inode; 91 + int ret = 0; 91 92 92 93 if (!dentry) 93 94 dentry = path->dentry; 94 95 95 96 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) 96 - return; 97 + return 0; 97 98 98 99 parent = dget_parent(dentry); 99 100 p_inode = parent->d_inode; ··· 107 106 mask |= FS_EVENT_ON_CHILD; 108 107 109 108 if (path) 110 - fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, 111 - dentry->d_name.name, 0); 109 + ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, 110 + dentry->d_name.name, 0); 112 111 else 113 - fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, 114 - dentry->d_name.name, 0); 112 + ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, 113 + dentry->d_name.name, 0); 115 114 } 116 115 117 116 dput(parent); 117 + 118 + return ret; 118 119 } 119 120 EXPORT_SYMBOL_GPL(__fsnotify_parent); 120 121 ··· 255 252 256 253 if (inode_group > vfsmount_group) { 257 254 /* handle inode */ 258 - send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, 259 - data_is, cookie, file_name, &event); 255 + ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, 256 + data_is, cookie, file_name, &event); 260 257 /* we didn't use the vfsmount_mark */ 261 258 vfsmount_group = NULL; 262 259 } else if (vfsmount_group > inode_group) { 263 - send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, 264 - data_is, cookie, file_name, &event); 260 + ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, 261 + data_is, cookie, file_name, &event); 265 262 inode_group = NULL; 266 263 } else { 267 - send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, 268 - mask, data, data_is, cookie, file_name, 269 - &event); 264 + ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, 265 + mask, data, data_is, cookie, file_name, 266 + &event); 270 267 } 268 + 269 + if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS)) 270 + goto out; 271 271 272 272 if (inode_group) 273 273 inode_node = srcu_dereference(inode_node->next, ··· 279 273 vfsmount_node = srcu_dereference(vfsmount_node->next, 280 274 &fsnotify_mark_srcu); 281 275 } 282 - 276 + ret = 0; 277 + out: 283 278 srcu_read_unlock(&fsnotify_mark_srcu, idx); 284 279 /* 285 280 * fsnotify_create_event() took a reference so the event can't be cleaned
+7 -2
fs/notify/inode_mark.c
··· 177 177 * Attach an initialized mark to a given inode. 178 178 * These marks may be used for the fsnotify backend to determine which 179 179 * event types should be delivered to which group and for which inodes. These 180 - * marks are ordered according to the group's location in memory. 180 + * marks are ordered according to priority, highest number first, and then by 181 + * the group's location in memory. 181 182 */ 182 183 int fsnotify_add_inode_mark(struct fsnotify_mark *mark, 183 184 struct fsnotify_group *group, struct inode *inode, ··· 212 211 goto out; 213 212 } 214 213 215 - if (mark->group < lmark->group) 214 + if (mark->group->priority < lmark->group->priority) 215 + continue; 216 + 217 + if ((mark->group->priority == lmark->group->priority) && 218 + (mark->group < lmark->group)) 216 219 continue; 217 220 218 221 hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list);
+1 -1
fs/notify/inotify/inotify_user.c
··· 862 862 BUILD_BUG_ON(IN_Q_OVERFLOW != FS_Q_OVERFLOW); 863 863 BUILD_BUG_ON(IN_IGNORED != FS_IN_IGNORED); 864 864 BUILD_BUG_ON(IN_EXCL_UNLINK != FS_EXCL_UNLINK); 865 - BUILD_BUG_ON(IN_ISDIR != FS_IN_ISDIR); 865 + BUILD_BUG_ON(IN_ISDIR != FS_ISDIR); 866 866 BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT); 867 867 868 868 BUG_ON(hweight32(ALL_INOTIFY_BITS) != 21);
+5 -1
fs/notify/vfsmount_mark.c
··· 169 169 goto out; 170 170 } 171 171 172 - if (mark->group < lmark->group) 172 + if (mark->group->priority < lmark->group->priority) 173 + continue; 174 + 175 + if ((mark->group->priority == lmark->group->priority) && 176 + (mark->group < lmark->group)) 173 177 continue; 174 178 175 179 hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list);
+1
include/linux/Kbuild
··· 118 118 header-y += ext2_fs.h 119 119 header-y += fadvise.h 120 120 header-y += falloc.h 121 + header-y += fanotify.h 121 122 header-y += fb.h 122 123 header-y += fcntl.h 123 124 header-y += fd.h
+27 -9
include/linux/fanotify.h
··· 6 6 /* the following events that user-space can register for */ 7 7 #define FAN_ACCESS 0x00000001 /* File was accessed */ 8 8 #define FAN_MODIFY 0x00000002 /* File was modified */ 9 - #define FAN_CLOSE_WRITE 0x00000008 /* Unwrittable file closed */ 10 - #define FAN_CLOSE_NOWRITE 0x00000010 /* Writtable file closed */ 9 + #define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */ 10 + #define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ 11 11 #define FAN_OPEN 0x00000020 /* File was opened */ 12 12 13 - #define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ 14 - 15 - /* FIXME currently Q's have no limit.... */ 16 13 #define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ 17 14 18 15 #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ 19 16 #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ 17 + 18 + #define FAN_ONDIR 0x40000000 /* event occurred against dir */ 19 + 20 + #define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */ 20 21 21 22 /* helper events */ 22 23 #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ ··· 26 25 #define FAN_CLOEXEC 0x00000001 27 26 #define FAN_NONBLOCK 0x00000002 28 27 29 - #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK) 28 + /* These are NOT bitwise flags. Both bits are used togther. */ 29 + #define FAN_CLASS_NOTIF 0x00000000 30 + #define FAN_CLASS_CONTENT 0x00000004 31 + #define FAN_CLASS_PRE_CONTENT 0x00000008 32 + #define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ 33 + FAN_CLASS_PRE_CONTENT) 34 + 35 + #define FAN_UNLIMITED_QUEUE 0x00000010 36 + #define FAN_UNLIMITED_MARKS 0x00000020 37 + 38 + #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ 39 + FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\ 40 + FAN_UNLIMITED_MARKS) 30 41 31 42 /* flags used for fanotify_modify_mark() */ 32 43 #define FAN_MARK_ADD 0x00000001 ··· 49 36 #define FAN_MARK_IGNORED_MASK 0x00000020 50 37 #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 51 38 #define FAN_MARK_FLUSH 0x00000080 39 + #ifdef __KERNEL__ 40 + /* not valid from userspace, only kernel internal */ 41 + #define FAN_MARK_ONDIR 0x00000100 42 + #endif 52 43 53 44 #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ 54 45 FAN_MARK_REMOVE |\ ··· 60 43 FAN_MARK_ONLYDIR |\ 61 44 FAN_MARK_MOUNT |\ 62 45 FAN_MARK_IGNORED_MASK |\ 63 - FAN_MARK_IGNORED_SURV_MODIFY) 46 + FAN_MARK_IGNORED_SURV_MODIFY |\ 47 + FAN_MARK_FLUSH) 64 48 65 49 /* 66 50 * All of the events - we build the list by hand so that we can add flags in ··· 88 70 struct fanotify_event_metadata { 89 71 __u32 event_len; 90 72 __u32 vers; 91 - __u64 mask; 73 + __aligned_u64 mask; 92 74 __s32 fd; 93 75 __s32 pid; 94 - } __attribute__ ((packed)); 76 + }; 95 77 96 78 struct fanotify_response { 97 79 __s32 fd;
+22 -16
include/linux/fsnotify.h
··· 26 26 } 27 27 28 28 /* Notify this dentry's parent about a child's events. */ 29 - static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 29 + static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 30 30 { 31 31 if (!dentry) 32 32 dentry = path->dentry; 33 33 34 - __fsnotify_parent(path, dentry, mask); 34 + return __fsnotify_parent(path, dentry, mask); 35 35 } 36 36 37 37 /* simple call site for access decisions */ ··· 40 40 struct path *path = &file->f_path; 41 41 struct inode *inode = path->dentry->d_inode; 42 42 __u32 fsnotify_mask = 0; 43 + int ret; 43 44 44 45 if (file->f_mode & FMODE_NONOTIFY) 45 46 return 0; ··· 52 51 fsnotify_mask = FS_ACCESS_PERM; 53 52 else 54 53 BUG(); 54 + 55 + ret = fsnotify_parent(path, NULL, fsnotify_mask); 56 + if (ret) 57 + return ret; 55 58 56 59 return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 57 60 } ··· 98 93 old_dir_mask |= FS_DN_RENAME; 99 94 100 95 if (isdir) { 101 - old_dir_mask |= FS_IN_ISDIR; 102 - new_dir_mask |= FS_IN_ISDIR; 96 + old_dir_mask |= FS_ISDIR; 97 + new_dir_mask |= FS_ISDIR; 103 98 } 104 99 105 100 fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); ··· 137 132 __u32 mask = FS_DELETE; 138 133 139 134 if (isdir) 140 - mask |= FS_IN_ISDIR; 135 + mask |= FS_ISDIR; 141 136 142 137 fsnotify_parent(NULL, dentry, mask); 143 138 } ··· 179 174 */ 180 175 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) 181 176 { 182 - __u32 mask = (FS_CREATE | FS_IN_ISDIR); 177 + __u32 mask = (FS_CREATE | FS_ISDIR); 183 178 struct inode *d_inode = dentry->d_inode; 184 179 185 180 audit_inode_child(dentry, inode); ··· 197 192 __u32 mask = FS_ACCESS; 198 193 199 194 if (S_ISDIR(inode->i_mode)) 200 - mask |= FS_IN_ISDIR; 195 + mask |= FS_ISDIR; 201 196 202 197 if (!(file->f_mode & FMODE_NONOTIFY)) { 203 198 fsnotify_parent(path, NULL, mask); ··· 215 210 __u32 mask = FS_MODIFY; 216 211 217 212 if (S_ISDIR(inode->i_mode)) 218 - mask |= FS_IN_ISDIR; 213 + mask |= FS_ISDIR; 219 214 220 215 if (!(file->f_mode & FMODE_NONOTIFY)) { 221 216 fsnotify_parent(path, NULL, mask); ··· 233 228 __u32 mask = FS_OPEN; 234 229 235 230 if (S_ISDIR(inode->i_mode)) 236 - mask |= FS_IN_ISDIR; 231 + mask |= FS_ISDIR; 237 232 238 - if (!(file->f_mode & FMODE_NONOTIFY)) { 239 - fsnotify_parent(path, NULL, mask); 240 - fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 241 - } 233 + /* FMODE_NONOTIFY must never be set from user */ 234 + file->f_mode &= ~FMODE_NONOTIFY; 235 + 236 + fsnotify_parent(path, NULL, mask); 237 + fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 242 238 } 243 239 244 240 /* ··· 253 247 __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; 254 248 255 249 if (S_ISDIR(inode->i_mode)) 256 - mask |= FS_IN_ISDIR; 250 + mask |= FS_ISDIR; 257 251 258 252 if (!(file->f_mode & FMODE_NONOTIFY)) { 259 253 fsnotify_parent(path, NULL, mask); ··· 270 264 __u32 mask = FS_ATTRIB; 271 265 272 266 if (S_ISDIR(inode->i_mode)) 273 - mask |= FS_IN_ISDIR; 267 + mask |= FS_ISDIR; 274 268 275 269 fsnotify_parent(NULL, dentry, mask); 276 270 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); ··· 305 299 306 300 if (mask) { 307 301 if (S_ISDIR(inode->i_mode)) 308 - mask |= FS_IN_ISDIR; 302 + mask |= FS_ISDIR; 309 303 310 304 fsnotify_parent(NULL, dentry, mask); 311 305 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+20 -6
include/linux/fsnotify_backend.h
··· 45 45 #define FS_ACCESS_PERM 0x00020000 /* access event in a permissions hook */ 46 46 47 47 #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ 48 - #define FS_IN_ISDIR 0x40000000 /* event occurred against dir */ 48 + #define FS_ISDIR 0x40000000 /* event occurred against dir */ 49 49 #define FS_IN_ONESHOT 0x80000000 /* only send event once */ 50 50 51 51 #define FS_DN_RENAME 0x10000000 /* file renamed */ ··· 64 64 65 65 #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) 66 66 67 + #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM) 68 + 67 69 #define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ 68 70 FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \ 69 71 FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \ 70 72 FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \ 71 73 FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ 72 74 FS_OPEN_PERM | FS_ACCESS_PERM | FS_EXCL_UNLINK | \ 73 - FS_IN_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ 75 + FS_ISDIR | FS_IN_ONESHOT | FS_DN_RENAME | \ 74 76 FS_DN_MULTISHOT | FS_EVENT_ON_CHILD) 75 77 76 78 struct fsnotify_group; ··· 131 129 wait_queue_head_t notification_waitq; /* read() on the notification file blocks on this waitq */ 132 130 unsigned int q_len; /* events on the queue */ 133 131 unsigned int max_events; /* maximum events allowed on the list */ 132 + /* 133 + * Valid fsnotify group priorities. Events are send in order from highest 134 + * priority to lowest priority. We default to the lowest priority. 135 + */ 136 + #define FS_PRIO_0 0 /* normal notifiers, no permissions */ 137 + #define FS_PRIO_1 1 /* fanotify content based access control */ 138 + #define FS_PRIO_2 2 /* fanotify pre-content access */ 139 + unsigned int priority; 134 140 135 141 /* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ 136 142 spinlock_t mark_lock; /* protect marks_list */ ··· 169 159 bool bypass_perm; /* protected by access_mutex */ 170 160 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ 171 161 int f_flags; 162 + unsigned int max_marks; 163 + struct user_struct *user; 172 164 } fanotify_data; 173 165 #endif /* CONFIG_FANOTIFY */ 174 166 }; ··· 287 275 struct fsnotify_inode_mark i; 288 276 struct fsnotify_vfsmount_mark m; 289 277 }; 290 - __u32 ignored_mask; /* events types to ignore */ 291 278 struct list_head free_g_list; /* tmp list used when freeing this mark */ 279 + __u32 ignored_mask; /* events types to ignore */ 292 280 #define FSNOTIFY_MARK_FLAG_INODE 0x01 293 281 #define FSNOTIFY_MARK_FLAG_VFSMOUNT 0x02 294 282 #define FSNOTIFY_MARK_FLAG_OBJECT_PINNED 0x04 ··· 306 294 /* main fsnotify call to send events */ 307 295 extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, 308 296 const unsigned char *name, u32 cookie); 309 - extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); 297 + extern int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask); 310 298 extern void __fsnotify_inode_delete(struct inode *inode); 311 299 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); 312 300 extern u32 fsnotify_get_cookie(void); ··· 435 423 return 0; 436 424 } 437 425 438 - static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 439 - {} 426 + static inline int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 427 + { 428 + return 0; 429 + } 440 430 441 431 static inline void __fsnotify_inode_delete(struct inode *inode) 442 432 {}
+3
include/linux/sched.h
··· 672 672 atomic_t inotify_watches; /* How many inotify watches does this user have? */ 673 673 atomic_t inotify_devs; /* How many inotify devs does this user have opened? */ 674 674 #endif 675 + #ifdef CONFIG_FANOTIFY 676 + atomic_t fanotify_listeners; 677 + #endif 675 678 #ifdef CONFIG_EPOLL 676 679 atomic_t epoll_watches; /* The number of file descriptors currently watched */ 677 680 #endif