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

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

Pull fsnotify updates from Jan Kara:
"This contains cleanups of the fsnotify name removal hook and also a
patch to disable fanotify permission events for 'proc' filesystem"

* tag 'fsnotify_for_v5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
fsnotify: get rid of fsnotify_nameremove()
fsnotify: move fsnotify_nameremove() hook out of d_delete()
configfs: call fsnotify_rmdir() hook
debugfs: call fsnotify_{unlink,rmdir}() hooks
debugfs: simplify __debugfs_remove_file()
devpts: call fsnotify_unlink() hook
tracefs: call fsnotify_{unlink,rmdir}() hooks
rpc_pipefs: call fsnotify_{unlink,rmdir}() hooks
btrfs: call fsnotify_rmdir() hook
fsnotify: add empty fsnotify_{unlink,rmdir}() hooks
fanotify: Disallow permission events for proc filesystem

+76 -71
-5
fs/afs/dir_silly.c
··· 60 60 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) 61 61 afs_edit_dir_add(dvnode, &new->d_name, 62 62 &vnode->fid, afs_edit_dir_for_silly_1); 63 - 64 - /* vfs_unlink and the like do not issue this when a file is 65 - * sillyrenamed, so do it here. 66 - */ 67 - fsnotify_nameremove(old, 0); 68 63 } 69 64 70 65 kfree(scb);
+3 -1
fs/btrfs/ioctl.c
··· 2928 2928 inode_lock(inode); 2929 2929 err = btrfs_delete_subvolume(dir, dentry); 2930 2930 inode_unlock(inode); 2931 - if (!err) 2931 + if (!err) { 2932 + fsnotify_rmdir(dir, dentry); 2932 2933 d_delete(dentry); 2934 + } 2933 2935 2934 2936 out_dput: 2935 2937 dput(dentry);
+3
fs/configfs/dir.c
··· 13 13 #undef DEBUG 14 14 15 15 #include <linux/fs.h> 16 + #include <linux/fsnotify.h> 16 17 #include <linux/mount.h> 17 18 #include <linux/module.h> 18 19 #include <linux/slab.h> ··· 1789 1788 configfs_detach_group(&group->cg_item); 1790 1789 d_inode(dentry)->i_flags |= S_DEAD; 1791 1790 dont_mount(dentry); 1791 + fsnotify_rmdir(d_inode(parent), dentry); 1792 1792 d_delete(dentry); 1793 1793 inode_unlock(d_inode(parent)); 1794 1794 ··· 1918 1916 configfs_detach_group(&group->cg_item); 1919 1917 d_inode(dentry)->i_flags |= S_DEAD; 1920 1918 dont_mount(dentry); 1919 + fsnotify_rmdir(d_inode(root), dentry); 1921 1920 inode_unlock(d_inode(dentry)); 1922 1921 1923 1922 d_delete(dentry);
-2
fs/dcache.c
··· 2372 2372 void d_delete(struct dentry * dentry) 2373 2373 { 2374 2374 struct inode *inode = dentry->d_inode; 2375 - int isdir = d_is_dir(dentry); 2376 2375 2377 2376 spin_lock(&inode->i_lock); 2378 2377 spin_lock(&dentry->d_lock); ··· 2386 2387 spin_unlock(&dentry->d_lock); 2387 2388 spin_unlock(&inode->i_lock); 2388 2389 } 2389 - fsnotify_nameremove(dentry, isdir); 2390 2390 } 2391 2391 EXPORT_SYMBOL(d_delete); 2392 2392
+10 -11
fs/debugfs/inode.c
··· 617 617 } 618 618 EXPORT_SYMBOL_GPL(debugfs_create_symlink); 619 619 620 - static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent) 620 + static void __debugfs_file_removed(struct dentry *dentry) 621 621 { 622 622 struct debugfs_fsdata *fsd; 623 - 624 - simple_unlink(d_inode(parent), dentry); 625 - d_delete(dentry); 626 623 627 624 /* 628 625 * Paired with the closing smp_mb() implied by a successful ··· 641 644 642 645 if (simple_positive(dentry)) { 643 646 dget(dentry); 644 - if (!d_is_reg(dentry)) { 645 - if (d_is_dir(dentry)) 646 - ret = simple_rmdir(d_inode(parent), dentry); 647 - else 648 - simple_unlink(d_inode(parent), dentry); 647 + if (d_is_dir(dentry)) { 648 + ret = simple_rmdir(d_inode(parent), dentry); 649 649 if (!ret) 650 - d_delete(dentry); 650 + fsnotify_rmdir(d_inode(parent), dentry); 651 651 } else { 652 - __debugfs_remove_file(dentry, parent); 652 + simple_unlink(d_inode(parent), dentry); 653 + fsnotify_unlink(d_inode(parent), dentry); 653 654 } 655 + if (!ret) 656 + d_delete(dentry); 657 + if (d_is_reg(dentry)) 658 + __debugfs_file_removed(dentry); 654 659 dput(dentry); 655 660 } 656 661 return ret;
+1
fs/devpts/inode.c
··· 621 621 622 622 dentry->d_fsdata = NULL; 623 623 drop_nlink(dentry->d_inode); 624 + fsnotify_unlink(d_inode(dentry->d_parent), dentry); 624 625 d_delete(dentry); 625 626 dput(dentry); /* d_alloc_name() in devpts_pty_new() */ 626 627 }
+2
fs/namei.c
··· 3883 3883 dentry->d_inode->i_flags |= S_DEAD; 3884 3884 dont_mount(dentry); 3885 3885 detach_mounts(dentry); 3886 + fsnotify_rmdir(dir, dentry); 3886 3887 3887 3888 out: 3888 3889 inode_unlock(dentry->d_inode); ··· 4000 3999 if (!error) { 4001 4000 dont_mount(dentry); 4002 4001 detach_mounts(dentry); 4002 + fsnotify_unlink(dir, dentry); 4003 4003 } 4004 4004 } 4005 4005 }
-6
fs/nfs/unlink.c
··· 396 396 nfs_cancel_async_unlink(dentry); 397 397 return; 398 398 } 399 - 400 - /* 401 - * vfs_unlink and the like do not issue this when a file is 402 - * sillyrenamed, so do it here. 403 - */ 404 - fsnotify_nameremove(dentry, 0); 405 399 } 406 400 407 401 #define SILLYNAME_PREFIX ".nfs"
+22
fs/notify/fanotify/fanotify_user.c
··· 920 920 return 0; 921 921 } 922 922 923 + static int fanotify_events_supported(struct path *path, __u64 mask) 924 + { 925 + /* 926 + * Some filesystems such as 'proc' acquire unusual locks when opening 927 + * files. For them fanotify permission events have high chances of 928 + * deadlocking the system - open done when reporting fanotify event 929 + * blocks on this "unusual" lock while another process holding the lock 930 + * waits for fanotify permission event to be answered. Just disallow 931 + * permission events for such filesystems. 932 + */ 933 + if (mask & FANOTIFY_PERM_EVENTS && 934 + path->mnt->mnt_sb->s_type->fs_flags & FS_DISALLOW_NOTIFY_PERM) 935 + return -EINVAL; 936 + return 0; 937 + } 938 + 923 939 static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, 924 940 int dfd, const char __user *pathname) 925 941 { ··· 1033 1017 ret = fanotify_find_path(dfd, pathname, &path, flags); 1034 1018 if (ret) 1035 1019 goto fput_and_out; 1020 + 1021 + if (flags & FAN_MARK_ADD) { 1022 + ret = fanotify_events_supported(&path, mask); 1023 + if (ret) 1024 + goto path_put_and_out; 1025 + } 1036 1026 1037 1027 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { 1038 1028 ret = fanotify_test_fid(&path, &__fsid);
-41
fs/notify/fsnotify.c
··· 95 95 } 96 96 97 97 /* 98 - * fsnotify_nameremove - a filename was removed from a directory 99 - * 100 - * This is mostly called under parent vfs inode lock so name and 101 - * dentry->d_parent should be stable. However there are some corner cases where 102 - * inode lock is not held. So to be on the safe side and be reselient to future 103 - * callers and out of tree users of d_delete(), we do not assume that d_parent 104 - * and d_name are stable and we use dget_parent() and 105 - * take_dentry_name_snapshot() to grab stable references. 106 - */ 107 - void fsnotify_nameremove(struct dentry *dentry, int isdir) 108 - { 109 - struct dentry *parent; 110 - struct name_snapshot name; 111 - __u32 mask = FS_DELETE; 112 - 113 - /* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */ 114 - if (IS_ROOT(dentry)) 115 - return; 116 - 117 - if (isdir) 118 - mask |= FS_ISDIR; 119 - 120 - parent = dget_parent(dentry); 121 - /* Avoid unneeded take_dentry_name_snapshot() */ 122 - if (!(d_inode(parent)->i_fsnotify_mask & FS_DELETE) && 123 - !(dentry->d_sb->s_fsnotify_mask & FS_DELETE)) 124 - goto out_dput; 125 - 126 - take_dentry_name_snapshot(&name, dentry); 127 - 128 - fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE, 129 - &name.name, 0); 130 - 131 - release_dentry_name_snapshot(&name); 132 - 133 - out_dput: 134 - dput(parent); 135 - } 136 - EXPORT_SYMBOL(fsnotify_nameremove); 137 - 138 - /* 139 98 * Given an inode, first check if we care what happens to our children. Inotify 140 99 * and dnotify both tell their parents about events. If we care about any event 141 100 * on a child we run all of our children and set a dentry flag saying that the
+1 -1
fs/proc/root.c
··· 211 211 .init_fs_context = proc_init_fs_context, 212 212 .parameters = &proc_fs_parameters, 213 213 .kill_sb = proc_kill_sb, 214 - .fs_flags = FS_USERNS_MOUNT, 214 + .fs_flags = FS_USERNS_MOUNT | FS_DISALLOW_NOTIFY_PERM, 215 215 }; 216 216 217 217 void __init proc_root_init(void)
+3
fs/tracefs/inode.c
··· 505 505 switch (dentry->d_inode->i_mode & S_IFMT) { 506 506 case S_IFDIR: 507 507 ret = simple_rmdir(parent->d_inode, dentry); 508 + if (!ret) 509 + fsnotify_rmdir(parent->d_inode, dentry); 508 510 break; 509 511 default: 510 512 simple_unlink(parent->d_inode, dentry); 513 + fsnotify_unlink(parent->d_inode, dentry); 511 514 break; 512 515 } 513 516 if (!ret)
+1
include/linux/fs.h
··· 2184 2184 #define FS_BINARY_MOUNTDATA 2 2185 2185 #define FS_HAS_SUBTYPE 4 2186 2186 #define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ 2187 + #define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */ 2187 2188 #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ 2188 2189 int (*init_fs_context)(struct fs_context *); 2189 2190 const struct fs_parameter_description *parameters;
+26
include/linux/fsnotify.h
··· 189 189 } 190 190 191 191 /* 192 + * fsnotify_unlink - 'name' was unlinked 193 + * 194 + * Caller must make sure that dentry->d_name is stable. 195 + */ 196 + static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry) 197 + { 198 + /* Expected to be called before d_delete() */ 199 + WARN_ON_ONCE(d_is_negative(dentry)); 200 + 201 + fsnotify_dirent(dir, dentry, FS_DELETE); 202 + } 203 + 204 + /* 192 205 * fsnotify_mkdir - directory 'name' was created 193 206 */ 194 207 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) ··· 209 196 audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); 210 197 211 198 fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR); 199 + } 200 + 201 + /* 202 + * fsnotify_rmdir - directory 'name' was removed 203 + * 204 + * Caller must make sure that dentry->d_name is stable. 205 + */ 206 + static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry) 207 + { 208 + /* Expected to be called before d_delete() */ 209 + WARN_ON_ONCE(d_is_negative(dentry)); 210 + 211 + fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR); 212 212 } 213 213 214 214 /*
-4
include/linux/fsnotify_backend.h
··· 357 357 extern void __fsnotify_inode_delete(struct inode *inode); 358 358 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); 359 359 extern void fsnotify_sb_delete(struct super_block *sb); 360 - extern void fsnotify_nameremove(struct dentry *dentry, int isdir); 361 360 extern u32 fsnotify_get_cookie(void); 362 361 363 362 static inline int fsnotify_inode_watches_children(struct inode *inode) ··· 524 525 {} 525 526 526 527 static inline void fsnotify_sb_delete(struct super_block *sb) 527 - {} 528 - 529 - static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) 530 528 {} 531 529 532 530 static inline void fsnotify_update_flags(struct dentry *dentry)
+4
net/sunrpc/rpc_pipe.c
··· 598 598 599 599 dget(dentry); 600 600 ret = simple_rmdir(dir, dentry); 601 + if (!ret) 602 + fsnotify_rmdir(dir, dentry); 601 603 d_delete(dentry); 602 604 dput(dentry); 603 605 return ret; ··· 611 609 612 610 dget(dentry); 613 611 ret = simple_unlink(dir, dentry); 612 + if (!ret) 613 + fsnotify_unlink(dir, dentry); 614 614 d_delete(dentry); 615 615 dput(dentry); 616 616 return ret;