Skip to content

Commit a8b98c8

Browse files
amir73iljankara
authored andcommitted
fanotify: fix permission model of unprivileged group
Reporting event->pid should depend on the privileges of the user that initialized the group, not the privileges of the user reading the events. Use an internal group flag FANOTIFY_UNPRIV to record the fact that the group was initialized by an unprivileged user. To be on the safe side, the premissions to setup filesystem and mount marks now require that both the user that initialized the group and the user setting up the mark have CAP_SYS_ADMIN. Link: https://lore.kernel.org/linux-fsdevel/CAOQ4uxiA77_P5vtv7e83g0+9d7B5W9ZTE4GfQEYbWmfT1rA=VA@mail.gmail.com/ Fixes: 7cea2a3 ("fanotify: support limited functionality for unprivileged users") Cc: <[email protected]> # v5.12+ Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Matthew Bobrowski <[email protected]> Acked-by: Christian Brauner <[email protected]> Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent b577750 commit a8b98c8

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

fs/notify/fanotify/fanotify_user.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -424,11 +424,18 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
424424
* events generated by the listener process itself, without disclosing
425425
* the pids of other processes.
426426
*/
427-
if (!capable(CAP_SYS_ADMIN) &&
427+
if (FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
428428
task_tgid(current) != event->pid)
429429
metadata.pid = 0;
430430

431-
if (path && path->mnt && path->dentry) {
431+
/*
432+
* For now, fid mode is required for an unprivileged listener and
433+
* fid mode does not report fd in events. Keep this check anyway
434+
* for safety in case fid mode requirement is relaxed in the future
435+
* to allow unprivileged listener to get events with no fd and no fid.
436+
*/
437+
if (!FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV) &&
438+
path && path->mnt && path->dentry) {
432439
fd = create_fd(group, path, &f);
433440
if (fd < 0)
434441
return fd;
@@ -1040,6 +1047,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
10401047
int f_flags, fd;
10411048
unsigned int fid_mode = flags & FANOTIFY_FID_BITS;
10421049
unsigned int class = flags & FANOTIFY_CLASS_BITS;
1050+
unsigned int internal_flags = 0;
10431051

10441052
pr_debug("%s: flags=%x event_f_flags=%x\n",
10451053
__func__, flags, event_f_flags);
@@ -1053,6 +1061,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
10531061
*/
10541062
if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) || !fid_mode)
10551063
return -EPERM;
1064+
1065+
/*
1066+
* Setting the internal flag FANOTIFY_UNPRIV on the group
1067+
* prevents setting mount/filesystem marks on this group and
1068+
* prevents reporting pid and open fd in events.
1069+
*/
1070+
internal_flags |= FANOTIFY_UNPRIV;
10561071
}
10571072

10581073
#ifdef CONFIG_AUDITSYSCALL
@@ -1105,7 +1120,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
11051120
goto out_destroy_group;
11061121
}
11071122

1108-
group->fanotify_data.flags = flags;
1123+
group->fanotify_data.flags = flags | internal_flags;
11091124
group->memcg = get_mem_cgroup_from_mm(current->mm);
11101125

11111126
group->fanotify_data.merge_hash = fanotify_alloc_merge_hash();
@@ -1305,11 +1320,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
13051320
group = f.file->private_data;
13061321

13071322
/*
1308-
* An unprivileged user is not allowed to watch a mount point nor
1309-
* a filesystem.
1323+
* An unprivileged user is not allowed to setup mount nor filesystem
1324+
* marks. This also includes setting up such marks by a group that
1325+
* was initialized by an unprivileged user.
13101326
*/
13111327
ret = -EPERM;
1312-
if (!capable(CAP_SYS_ADMIN) &&
1328+
if ((!capable(CAP_SYS_ADMIN) ||
1329+
FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
13131330
mark_type != FAN_MARK_INODE)
13141331
goto fput_and_out;
13151332

@@ -1460,6 +1477,7 @@ static int __init fanotify_user_setup(void)
14601477
max_marks = clamp(max_marks, FANOTIFY_OLD_DEFAULT_MAX_MARKS,
14611478
FANOTIFY_DEFAULT_MAX_USER_MARKS);
14621479

1480+
BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
14631481
BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 10);
14641482
BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
14651483

fs/notify/fdinfo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ void fanotify_show_fdinfo(struct seq_file *m, struct file *f)
144144
struct fsnotify_group *group = f->private_data;
145145

146146
seq_printf(m, "fanotify flags:%x event-flags:%x\n",
147-
group->fanotify_data.flags,
147+
group->fanotify_data.flags & FANOTIFY_INIT_FLAGS,
148148
group->fanotify_data.f_flags);
149149

150150
show_fdinfo(m, f, fanotify_fdinfo);

include/linux/fanotify.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */
5151
#define FANOTIFY_INIT_FLAGS (FANOTIFY_ADMIN_INIT_FLAGS | \
5252
FANOTIFY_USER_INIT_FLAGS)
5353

54+
/* Internal group flags */
55+
#define FANOTIFY_UNPRIV 0x80000000
56+
#define FANOTIFY_INTERNAL_GROUP_FLAGS (FANOTIFY_UNPRIV)
57+
5458
#define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \
5559
FAN_MARK_FILESYSTEM)
5660

0 commit comments

Comments
 (0)