@@ -113,6 +113,7 @@ struct kmem_cache *fanotify_mark_cache __ro_after_init;
113113struct kmem_cache * fanotify_fid_event_cachep __ro_after_init ;
114114struct kmem_cache * fanotify_path_event_cachep __ro_after_init ;
115115struct kmem_cache * fanotify_perm_event_cachep __ro_after_init ;
116+ struct kmem_cache * fanotify_mnt_event_cachep __ro_after_init ;
116117
117118#define FANOTIFY_EVENT_ALIGN 4
118119#define FANOTIFY_FID_INFO_HDR_LEN \
@@ -123,6 +124,8 @@ struct kmem_cache *fanotify_perm_event_cachep __ro_after_init;
123124 (sizeof(struct fanotify_event_info_error))
124125#define FANOTIFY_RANGE_INFO_LEN \
125126 (sizeof(struct fanotify_event_info_range))
127+ #define FANOTIFY_MNT_INFO_LEN \
128+ (sizeof(struct fanotify_event_info_mnt))
126129
127130static int fanotify_fid_info_len (int fh_len , int name_len )
128131{
@@ -178,6 +181,8 @@ static size_t fanotify_event_len(unsigned int info_mode,
178181 fh_len = fanotify_event_object_fh_len (event );
179182 event_len += fanotify_fid_info_len (fh_len , dot_len );
180183 }
184+ if (fanotify_is_mnt_event (event -> mask ))
185+ event_len += FANOTIFY_MNT_INFO_LEN ;
181186
182187 if (info_mode & FAN_REPORT_PIDFD )
183188 event_len += FANOTIFY_PIDFD_INFO_LEN ;
@@ -405,6 +410,25 @@ static int process_access_response(struct fsnotify_group *group,
405410 return - ENOENT ;
406411}
407412
413+ static size_t copy_mnt_info_to_user (struct fanotify_event * event ,
414+ char __user * buf , int count )
415+ {
416+ struct fanotify_event_info_mnt info = { };
417+
418+ info .hdr .info_type = FAN_EVENT_INFO_TYPE_MNT ;
419+ info .hdr .len = FANOTIFY_MNT_INFO_LEN ;
420+
421+ if (WARN_ON (count < info .hdr .len ))
422+ return - EFAULT ;
423+
424+ info .mnt_id = FANOTIFY_ME (event )-> mnt_id ;
425+
426+ if (copy_to_user (buf , & info , sizeof (info )))
427+ return - EFAULT ;
428+
429+ return info .hdr .len ;
430+ }
431+
408432static size_t copy_error_info_to_user (struct fanotify_event * event ,
409433 char __user * buf , int count )
410434{
@@ -700,6 +724,15 @@ static int copy_info_records_to_user(struct fanotify_event *event,
700724 total_bytes += ret ;
701725 }
702726
727+ if (fanotify_is_mnt_event (event -> mask )) {
728+ ret = copy_mnt_info_to_user (event , buf , count );
729+ if (ret < 0 )
730+ return ret ;
731+ buf += ret ;
732+ count -= ret ;
733+ total_bytes += ret ;
734+ }
735+
703736 return total_bytes ;
704737}
705738
@@ -1508,6 +1541,14 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
15081541 if ((flags & FAN_REPORT_PIDFD ) && (flags & FAN_REPORT_TID ))
15091542 return - EINVAL ;
15101543
1544+ /* Don't allow mixing mnt events with inode events for now */
1545+ if (flags & FAN_REPORT_MNT ) {
1546+ if (class != FAN_CLASS_NOTIF )
1547+ return - EINVAL ;
1548+ if (flags & (FANOTIFY_FID_BITS | FAN_REPORT_FD_ERROR ))
1549+ return - EINVAL ;
1550+ }
1551+
15111552 if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS )
15121553 return - EINVAL ;
15131554
@@ -1767,7 +1808,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
17671808 int dfd , const char __user * pathname )
17681809{
17691810 struct inode * inode = NULL ;
1770- struct vfsmount * mnt = NULL ;
17711811 struct fsnotify_group * group ;
17721812 struct path path ;
17731813 struct fan_fsid __fsid , * fsid = NULL ;
@@ -1776,7 +1816,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
17761816 unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS ;
17771817 unsigned int ignore = flags & FANOTIFY_MARK_IGNORE_BITS ;
17781818 unsigned int obj_type , fid_mode ;
1779- void * obj ;
1819+ void * obj = NULL ;
17801820 u32 umask = 0 ;
17811821 int ret ;
17821822
@@ -1800,6 +1840,9 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18001840 case FAN_MARK_FILESYSTEM :
18011841 obj_type = FSNOTIFY_OBJ_TYPE_SB ;
18021842 break ;
1843+ case FAN_MARK_MNTNS :
1844+ obj_type = FSNOTIFY_OBJ_TYPE_MNTNS ;
1845+ break ;
18031846 default :
18041847 return - EINVAL ;
18051848 }
@@ -1847,6 +1890,19 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18471890 return - EINVAL ;
18481891 group = fd_file (f )-> private_data ;
18491892
1893+ /* Only report mount events on mnt namespace */
1894+ if (FAN_GROUP_FLAG (group , FAN_REPORT_MNT )) {
1895+ if (mask & ~FANOTIFY_MOUNT_EVENTS )
1896+ return - EINVAL ;
1897+ if (mark_type != FAN_MARK_MNTNS )
1898+ return - EINVAL ;
1899+ } else {
1900+ if (mask & FANOTIFY_MOUNT_EVENTS )
1901+ return - EINVAL ;
1902+ if (mark_type == FAN_MARK_MNTNS )
1903+ return - EINVAL ;
1904+ }
1905+
18501906 /*
18511907 * An unprivileged user is not allowed to setup mount nor filesystem
18521908 * marks. This also includes setting up such marks by a group that
@@ -1888,7 +1944,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18881944 * point.
18891945 */
18901946 fid_mode = FAN_GROUP_FLAG (group , FANOTIFY_FID_BITS );
1891- if (mask & ~(FANOTIFY_FD_EVENTS |FANOTIFY_EVENT_FLAGS ) &&
1947+ if (mask & ~(FANOTIFY_FD_EVENTS |FANOTIFY_MOUNT_EVENTS | FANOTIFY_EVENT_FLAGS ) &&
18921948 (!fid_mode || mark_type == FAN_MARK_MOUNT ))
18931949 return - EINVAL ;
18941950
@@ -1938,28 +1994,32 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
19381994 }
19391995
19401996 /* inode held in place by reference to path; group by fget on fd */
1941- if (mark_type == FAN_MARK_INODE ) {
1997+ if (obj_type == FSNOTIFY_OBJ_TYPE_INODE ) {
19421998 inode = path .dentry -> d_inode ;
19431999 obj = inode ;
1944- } else {
1945- mnt = path .mnt ;
1946- if (mark_type == FAN_MARK_MOUNT )
1947- obj = mnt ;
1948- else
1949- obj = mnt -> mnt_sb ;
2000+ } else if ( obj_type == FSNOTIFY_OBJ_TYPE_VFSMOUNT ) {
2001+ obj = path .mnt ;
2002+ } else if (obj_type == FSNOTIFY_OBJ_TYPE_SB ) {
2003+ obj = path . mnt -> mnt_sb ;
2004+ } else if ( obj_type == FSNOTIFY_OBJ_TYPE_MNTNS ) {
2005+ obj = mnt_ns_from_dentry ( path . dentry ) ;
19502006 }
19512007
2008+ ret = - EINVAL ;
2009+ if (!obj )
2010+ goto path_put_and_out ;
2011+
19522012 /*
19532013 * If some other task has this inode open for write we should not add
19542014 * an ignore mask, unless that ignore mask is supposed to survive
19552015 * modification changes anyway.
19562016 */
19572017 if (mark_cmd == FAN_MARK_ADD && (flags & FANOTIFY_MARK_IGNORE_BITS ) &&
19582018 !(flags & FAN_MARK_IGNORED_SURV_MODIFY )) {
1959- ret = mnt ? - EINVAL : - EISDIR ;
2019+ ret = ! inode ? - EINVAL : - EISDIR ;
19602020 /* FAN_MARK_IGNORE requires SURV_MODIFY for sb/mount/dir marks */
19612021 if (ignore == FAN_MARK_IGNORE &&
1962- (mnt || S_ISDIR (inode -> i_mode )))
2022+ (! inode || S_ISDIR (inode -> i_mode )))
19632023 goto path_put_and_out ;
19642024
19652025 ret = 0 ;
@@ -1968,7 +2028,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
19682028 }
19692029
19702030 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
1971- if (mnt || !S_ISDIR (inode -> i_mode )) {
2031+ if (! inode || !S_ISDIR (inode -> i_mode )) {
19722032 mask &= ~FAN_EVENT_ON_CHILD ;
19732033 umask = FAN_EVENT_ON_CHILD ;
19742034 /*
@@ -2042,7 +2102,7 @@ static int __init fanotify_user_setup(void)
20422102 FANOTIFY_DEFAULT_MAX_USER_MARKS );
20432103
20442104 BUILD_BUG_ON (FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS );
2045- BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) != 13 );
2105+ BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) != 14 );
20462106 BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_MARK_FLAGS ) != 11 );
20472107
20482108 fanotify_mark_cache = KMEM_CACHE (fanotify_mark ,
@@ -2055,6 +2115,7 @@ static int __init fanotify_user_setup(void)
20552115 fanotify_perm_event_cachep =
20562116 KMEM_CACHE (fanotify_perm_event , SLAB_PANIC );
20572117 }
2118+ fanotify_mnt_event_cachep = KMEM_CACHE (fanotify_mnt_event , SLAB_PANIC );
20582119
20592120 fanotify_max_queued_events = FANOTIFY_DEFAULT_MAX_EVENTS ;
20602121 init_user_ns .ucount_max [UCOUNT_FANOTIFY_GROUPS ] =
0 commit comments