@@ -1499,6 +1499,7 @@ static struct hlist_head *fanotify_alloc_merge_hash(void)
14991499/* fanotify syscalls */
15001500SYSCALL_DEFINE2 (fanotify_init , unsigned int , flags , unsigned int , event_f_flags )
15011501{
1502+ struct user_namespace * user_ns = current_user_ns ();
15021503 struct fsnotify_group * group ;
15031504 int f_flags , fd ;
15041505 unsigned int fid_mode = flags & FANOTIFY_FID_BITS ;
@@ -1513,10 +1514,11 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
15131514 /*
15141515 * An unprivileged user can setup an fanotify group with
15151516 * limited functionality - an unprivileged group is limited to
1516- * notification events with file handles and it cannot use
1517- * unlimited queue/marks.
1517+ * notification events with file handles or mount ids and it
1518+ * cannot use unlimited queue/marks.
15181519 */
1519- if ((flags & FANOTIFY_ADMIN_INIT_FLAGS ) || !fid_mode )
1520+ if ((flags & FANOTIFY_ADMIN_INIT_FLAGS ) ||
1521+ !(flags & (FANOTIFY_FID_BITS | FAN_REPORT_MNT )))
15201522 return - EPERM ;
15211523
15221524 /*
@@ -1595,8 +1597,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
15951597 }
15961598
15971599 /* Enforce groups limits per user in all containing user ns */
1598- group -> fanotify_data .ucounts = inc_ucount (current_user_ns (),
1599- current_euid (),
1600+ group -> fanotify_data .ucounts = inc_ucount (user_ns , current_euid (),
16001601 UCOUNT_FANOTIFY_GROUPS );
16011602 if (!group -> fanotify_data .ucounts ) {
16021603 fd = - EMFILE ;
@@ -1605,6 +1606,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
16051606
16061607 group -> fanotify_data .flags = flags | internal_flags ;
16071608 group -> memcg = get_mem_cgroup_from_mm (current -> mm );
1609+ group -> user_ns = get_user_ns (user_ns );
16081610
16091611 group -> fanotify_data .merge_hash = fanotify_alloc_merge_hash ();
16101612 if (!group -> fanotify_data .merge_hash ) {
@@ -1804,6 +1806,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18041806 struct fsnotify_group * group ;
18051807 struct path path ;
18061808 struct fan_fsid __fsid , * fsid = NULL ;
1809+ struct user_namespace * user_ns = NULL ;
1810+ struct mnt_namespace * mntns ;
18071811 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS ;
18081812 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
18091813 unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS ;
@@ -1897,12 +1901,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18971901 }
18981902
18991903 /*
1900- * An unprivileged user is not allowed to setup mount nor filesystem
1901- * marks. This also includes setting up such marks by a group that
1902- * was initialized by an unprivileged user.
1904+ * A user is allowed to setup sb/mount/mntns marks only if it is
1905+ * capable in the user ns where the group was created.
19031906 */
1904- if ((!capable (CAP_SYS_ADMIN ) ||
1905- FAN_GROUP_FLAG (group , FANOTIFY_UNPRIV )) &&
1907+ if (!ns_capable (group -> user_ns , CAP_SYS_ADMIN ) &&
19061908 mark_type != FAN_MARK_INODE )
19071909 return - EPERM ;
19081910
@@ -1986,18 +1988,31 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
19861988 fsid = & __fsid ;
19871989 }
19881990
1989- /* inode held in place by reference to path; group by fget on fd */
1991+ /*
1992+ * In addition to being capable in the user ns where group was created,
1993+ * the user also needs to be capable in the user ns associated with
1994+ * the filesystem or in the user ns associated with the mntns
1995+ * (when marking mntns).
1996+ */
19901997 if (obj_type == FSNOTIFY_OBJ_TYPE_INODE ) {
19911998 inode = path .dentry -> d_inode ;
19921999 obj = inode ;
19932000 } else if (obj_type == FSNOTIFY_OBJ_TYPE_VFSMOUNT ) {
2001+ user_ns = path .mnt -> mnt_sb -> s_user_ns ;
19942002 obj = path .mnt ;
19952003 } else if (obj_type == FSNOTIFY_OBJ_TYPE_SB ) {
2004+ user_ns = path .mnt -> mnt_sb -> s_user_ns ;
19962005 obj = path .mnt -> mnt_sb ;
19972006 } else if (obj_type == FSNOTIFY_OBJ_TYPE_MNTNS ) {
1998- obj = mnt_ns_from_dentry (path .dentry );
2007+ mntns = mnt_ns_from_dentry (path .dentry );
2008+ user_ns = mntns -> user_ns ;
2009+ obj = mntns ;
19992010 }
20002011
2012+ ret = - EPERM ;
2013+ if (user_ns && !ns_capable (user_ns , CAP_SYS_ADMIN ))
2014+ goto path_put_and_out ;
2015+
20012016 ret = - EINVAL ;
20022017 if (!obj )
20032018 goto path_put_and_out ;
0 commit comments