@@ -1499,6 +1499,7 @@ static struct hlist_head *fanotify_alloc_merge_hash(void)
1499
1499
/* fanotify syscalls */
1500
1500
SYSCALL_DEFINE2 (fanotify_init , unsigned int , flags , unsigned int , event_f_flags )
1501
1501
{
1502
+ struct user_namespace * user_ns = current_user_ns ();
1502
1503
struct fsnotify_group * group ;
1503
1504
int f_flags , fd ;
1504
1505
unsigned int fid_mode = flags & FANOTIFY_FID_BITS ;
@@ -1513,10 +1514,11 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
1513
1514
/*
1514
1515
* An unprivileged user can setup an fanotify group with
1515
1516
* 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.
1518
1519
*/
1519
- if ((flags & FANOTIFY_ADMIN_INIT_FLAGS ) || !fid_mode )
1520
+ if ((flags & FANOTIFY_ADMIN_INIT_FLAGS ) ||
1521
+ !(flags & (FANOTIFY_FID_BITS | FAN_REPORT_MNT )))
1520
1522
return - EPERM ;
1521
1523
1522
1524
/*
@@ -1595,8 +1597,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
1595
1597
}
1596
1598
1597
1599
/* 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 (),
1600
1601
UCOUNT_FANOTIFY_GROUPS );
1601
1602
if (!group -> fanotify_data .ucounts ) {
1602
1603
fd = - EMFILE ;
@@ -1605,6 +1606,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
1605
1606
1606
1607
group -> fanotify_data .flags = flags | internal_flags ;
1607
1608
group -> memcg = get_mem_cgroup_from_mm (current -> mm );
1609
+ group -> user_ns = get_user_ns (user_ns );
1608
1610
1609
1611
group -> fanotify_data .merge_hash = fanotify_alloc_merge_hash ();
1610
1612
if (!group -> fanotify_data .merge_hash ) {
@@ -1804,6 +1806,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1804
1806
struct fsnotify_group * group ;
1805
1807
struct path path ;
1806
1808
struct fan_fsid __fsid , * fsid = NULL ;
1809
+ struct user_namespace * user_ns = NULL ;
1810
+ struct mnt_namespace * mntns ;
1807
1811
u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS ;
1808
1812
unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
1809
1813
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,
1897
1901
}
1898
1902
1899
1903
/*
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.
1903
1906
*/
1904
- if ((!capable (CAP_SYS_ADMIN ) ||
1905
- FAN_GROUP_FLAG (group , FANOTIFY_UNPRIV )) &&
1907
+ if (!ns_capable (group -> user_ns , CAP_SYS_ADMIN ) &&
1906
1908
mark_type != FAN_MARK_INODE )
1907
1909
return - EPERM ;
1908
1910
@@ -1986,18 +1988,31 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1986
1988
fsid = & __fsid ;
1987
1989
}
1988
1990
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
+ */
1990
1997
if (obj_type == FSNOTIFY_OBJ_TYPE_INODE ) {
1991
1998
inode = path .dentry -> d_inode ;
1992
1999
obj = inode ;
1993
2000
} else if (obj_type == FSNOTIFY_OBJ_TYPE_VFSMOUNT ) {
2001
+ user_ns = path .mnt -> mnt_sb -> s_user_ns ;
1994
2002
obj = path .mnt ;
1995
2003
} else if (obj_type == FSNOTIFY_OBJ_TYPE_SB ) {
2004
+ user_ns = path .mnt -> mnt_sb -> s_user_ns ;
1996
2005
obj = path .mnt -> mnt_sb ;
1997
2006
} 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 ;
1999
2010
}
2000
2011
2012
+ ret = - EPERM ;
2013
+ if (user_ns && !ns_capable (user_ns , CAP_SYS_ADMIN ))
2014
+ goto path_put_and_out ;
2015
+
2001
2016
ret = - EINVAL ;
2002
2017
if (!obj )
2003
2018
goto path_put_and_out ;
0 commit comments