summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2019-05-15 10:28:34 -0400
committerJan Kara <jack@suse.cz>2019-05-28 12:10:07 -0400
commit0b3b094ac9a7bb1fcf5d694f3ec981e6864a63d3 (patch)
tree71e5065d0213798e38d809f0d32fcbba047db6e5
parentcd6c84d8f0cdc911df435bb075ba22ce3c605b07 (diff)
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>
-rw-r--r--fs/notify/fanotify/fanotify_user.c22
-rw-r--r--fs/proc/root.c2
-rw-r--r--include/linux/fs.h1
3 files changed, 24 insertions, 1 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index a90bb19dcfa2..91006f47e420 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -920,6 +920,22 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)
920 return 0; 920 return 0;
921} 921}
922 922
923static 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
923static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, 939static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
924 int dfd, const char __user *pathname) 940 int dfd, const char __user *pathname)
925{ 941{
@@ -1018,6 +1034,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1018 if (ret) 1034 if (ret)
1019 goto fput_and_out; 1035 goto fput_and_out;
1020 1036
1037 if (flags & FAN_MARK_ADD) {
1038 ret = fanotify_events_supported(&path, mask);
1039 if (ret)
1040 goto path_put_and_out;
1041 }
1042
1021 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) { 1043 if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
1022 ret = fanotify_test_fid(&path, &__fsid); 1044 ret = fanotify_test_fid(&path, &__fsid);
1023 if (ret) 1045 if (ret)
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 8b145e7b9661..522199e9525e 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -211,7 +211,7 @@ static struct file_system_type proc_fs_type = {
211 .init_fs_context = proc_init_fs_context, 211 .init_fs_context = proc_init_fs_context,
212 .parameters = &proc_fs_parameters, 212 .parameters = &proc_fs_parameters,
213 .kill_sb = proc_kill_sb, 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
217void __init proc_root_init(void) 217void __init proc_root_init(void)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f7fdfe93e25d..c7136c98b5ba 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2184,6 +2184,7 @@ struct file_system_type {
2184#define FS_BINARY_MOUNTDATA 2 2184#define FS_BINARY_MOUNTDATA 2
2185#define FS_HAS_SUBTYPE 4 2185#define FS_HAS_SUBTYPE 4
2186#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ 2186#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
2187#define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */
2187#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ 2188#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
2188 int (*init_fs_context)(struct fs_context *); 2189 int (*init_fs_context)(struct fs_context *);
2189 const struct fs_parameter_description *parameters; 2190 const struct fs_parameter_description *parameters;