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

fanotify: Disallow permission events for proc filesystem

Proc filesystem has special locking rules for various files. Thus
fanotify which opens files on event delivery can easily deadlock
against another process that waits for fanotify permission event to be
handled. Since permission events on /proc have doubtful value anyway,
just disallow them.

Link: https://lore.kernel.org/linux-fsdevel/20190320131642.GE9485@quack2.suse.cz/
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>

Jan Kara 0b3b094a cd6c84d8

+24 -1
+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);
+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)
+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;