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

Configure Feed

Select the types of activity you want to include in your feed.

fanotify: support limited functionality for unprivileged users

Add limited support for unprivileged fanotify groups.
An unprivileged users is not allowed to get an open file descriptor in
the event nor the process pid of another process. An unprivileged user
cannot request permission events, cannot set mount/filesystem marks and
cannot request unlimited queue/marks.

This enables the limited functionality similar to inotify when watching a
set of files and directories for OPEN/ACCESS/MODIFY/CLOSE events, without
requiring SYS_CAP_ADMIN privileges.

The FAN_REPORT_DFID_NAME init flag, provide a method for an unprivileged
listener watching a set of directories (with FAN_EVENT_ON_CHILD) to monitor
all changes inside those directories.

This typically requires that the listener keeps a map of watched directory
fid to dirfd (O_PATH), where fid is obtained with name_to_handle_at()
before starting to watch for changes.

When getting an event, the reported fid of the parent should be resolved
to dirfd and fstatsat(2) with dirfd and name should be used to query the
state of the filesystem entry.

Link: https://lore.kernel.org/r/20210304112921.3996419-3-amir73il@gmail.com
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>

authored by

Amir Goldstein and committed by
Jan Kara
7cea2a3c 5b8fea65

+57 -8
+27 -2
fs/notify/fanotify/fanotify_user.c
··· 419 419 metadata.reserved = 0; 420 420 metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS; 421 421 metadata.pid = pid_vnr(event->pid); 422 + /* 423 + * For an unprivileged listener, event->pid can be used to identify the 424 + * events generated by the listener process itself, without disclosing 425 + * the pids of other processes. 426 + */ 427 + if (!capable(CAP_SYS_ADMIN) && 428 + task_tgid(current) != event->pid) 429 + metadata.pid = 0; 422 430 423 431 if (path && path->mnt && path->dentry) { 424 432 fd = create_fd(group, path, &f); ··· 1044 1036 pr_debug("%s: flags=%x event_f_flags=%x\n", 1045 1037 __func__, flags, event_f_flags); 1046 1038 1047 - if (!capable(CAP_SYS_ADMIN)) 1048 - return -EPERM; 1039 + if (!capable(CAP_SYS_ADMIN)) { 1040 + /* 1041 + * An unprivileged user can setup an fanotify group with 1042 + * limited functionality - an unprivileged group is limited to 1043 + * notification events with file handles and it cannot use 1044 + * unlimited queue/marks. 1045 + */ 1046 + if ((flags & FANOTIFY_ADMIN_INIT_FLAGS) || !fid_mode) 1047 + return -EPERM; 1048 + } 1049 1049 1050 1050 #ifdef CONFIG_AUDITSYSCALL 1051 1051 if (flags & ~(FANOTIFY_INIT_FLAGS | FAN_ENABLE_AUDIT)) ··· 1303 1287 if (unlikely(f.file->f_op != &fanotify_fops)) 1304 1288 goto fput_and_out; 1305 1289 group = f.file->private_data; 1290 + 1291 + /* 1292 + * An unprivileged user is not allowed to watch a mount point nor 1293 + * a filesystem. 1294 + */ 1295 + ret = -EPERM; 1296 + if (!capable(CAP_SYS_ADMIN) && 1297 + mark_type != FAN_MARK_INODE) 1298 + goto fput_and_out; 1306 1299 1307 1300 /* 1308 1301 * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not
+2 -1
fs/notify/fdinfo.c
··· 144 144 struct fsnotify_group *group = f->private_data; 145 145 146 146 seq_printf(m, "fanotify flags:%x event-flags:%x\n", 147 - group->fanotify_data.flags, group->fanotify_data.f_flags); 147 + group->fanotify_data.flags, 148 + group->fanotify_data.f_flags); 148 149 149 150 show_fdinfo(m, f, fanotify_fdinfo); 150 151 }
+28 -5
include/linux/fanotify.h
··· 18 18 * these constant, the programs may break if re-compiled with new uapi headers 19 19 * and then run on an old kernel. 20 20 */ 21 - #define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ 21 + 22 + /* Group classes where permission events are allowed */ 23 + #define FANOTIFY_PERM_CLASSES (FAN_CLASS_CONTENT | \ 22 24 FAN_CLASS_PRE_CONTENT) 25 + 26 + #define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FANOTIFY_PERM_CLASSES) 23 27 24 28 #define FANOTIFY_FID_BITS (FAN_REPORT_FID | FAN_REPORT_DFID_NAME) 25 29 26 - #define FANOTIFY_INIT_FLAGS (FANOTIFY_CLASS_BITS | FANOTIFY_FID_BITS | \ 27 - FAN_REPORT_TID | \ 28 - FAN_CLOEXEC | FAN_NONBLOCK | \ 29 - FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS) 30 + /* 31 + * fanotify_init() flags that require CAP_SYS_ADMIN. 32 + * We do not allow unprivileged groups to request permission events. 33 + * We do not allow unprivileged groups to get other process pid in events. 34 + * We do not allow unprivileged groups to use unlimited resources. 35 + */ 36 + #define FANOTIFY_ADMIN_INIT_FLAGS (FANOTIFY_PERM_CLASSES | \ 37 + FAN_REPORT_TID | \ 38 + FAN_UNLIMITED_QUEUE | \ 39 + FAN_UNLIMITED_MARKS) 40 + 41 + /* 42 + * fanotify_init() flags that are allowed for user without CAP_SYS_ADMIN. 43 + * FAN_CLASS_NOTIF is the only class we allow for unprivileged group. 44 + * We do not allow unprivileged groups to get file descriptors in events, 45 + * so one of the flags for reporting file handles is required. 46 + */ 47 + #define FANOTIFY_USER_INIT_FLAGS (FAN_CLASS_NOTIF | \ 48 + FANOTIFY_FID_BITS | \ 49 + FAN_CLOEXEC | FAN_NONBLOCK) 50 + 51 + #define FANOTIFY_INIT_FLAGS (FANOTIFY_ADMIN_INIT_FLAGS | \ 52 + FANOTIFY_USER_INIT_FLAGS) 30 53 31 54 #define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \ 32 55 FAN_MARK_FILESYSTEM)