2323
2424#include <asm/ioctls.h>
2525
26- #include "../../mount .h"
26+ #include "../fsnotify .h"
2727#include "../fdinfo.h"
2828#include "fanotify.h"
2929
@@ -1192,13 +1192,71 @@ static bool fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
11921192 return recalc ;
11931193}
11941194
1195+ struct fan_fsid {
1196+ struct super_block * sb ;
1197+ __kernel_fsid_t id ;
1198+ bool weak ;
1199+ };
1200+
1201+ static int fanotify_set_mark_fsid (struct fsnotify_group * group ,
1202+ struct fsnotify_mark * mark ,
1203+ struct fan_fsid * fsid )
1204+ {
1205+ struct fsnotify_mark_connector * conn ;
1206+ struct fsnotify_mark * old ;
1207+ struct super_block * old_sb = NULL ;
1208+
1209+ FANOTIFY_MARK (mark )-> fsid = fsid -> id ;
1210+ mark -> flags |= FSNOTIFY_MARK_FLAG_HAS_FSID ;
1211+ if (fsid -> weak )
1212+ mark -> flags |= FSNOTIFY_MARK_FLAG_WEAK_FSID ;
1213+
1214+ /* First mark added will determine if group is single or multi fsid */
1215+ if (list_empty (& group -> marks_list ))
1216+ return 0 ;
1217+
1218+ /* Find sb of an existing mark */
1219+ list_for_each_entry (old , & group -> marks_list , g_list ) {
1220+ conn = READ_ONCE (old -> connector );
1221+ if (!conn )
1222+ continue ;
1223+ old_sb = fsnotify_connector_sb (conn );
1224+ if (old_sb )
1225+ break ;
1226+ }
1227+
1228+ /* Only detached marks left? */
1229+ if (!old_sb )
1230+ return 0 ;
1231+
1232+ /* Do not allow mixing of marks with weak and strong fsid */
1233+ if ((mark -> flags ^ old -> flags ) & FSNOTIFY_MARK_FLAG_WEAK_FSID )
1234+ return - EXDEV ;
1235+
1236+ /* Allow mixing of marks with strong fsid from different fs */
1237+ if (!fsid -> weak )
1238+ return 0 ;
1239+
1240+ /* Do not allow mixing marks with weak fsid from different fs */
1241+ if (old_sb != fsid -> sb )
1242+ return - EXDEV ;
1243+
1244+ /* Do not allow mixing marks from different btrfs sub-volumes */
1245+ if (!fanotify_fsid_equal (& FANOTIFY_MARK (old )-> fsid ,
1246+ & FANOTIFY_MARK (mark )-> fsid ))
1247+ return - EXDEV ;
1248+
1249+ return 0 ;
1250+ }
1251+
11951252static struct fsnotify_mark * fanotify_add_new_mark (struct fsnotify_group * group ,
11961253 fsnotify_connp_t * connp ,
11971254 unsigned int obj_type ,
11981255 unsigned int fan_flags ,
1199- __kernel_fsid_t * fsid )
1256+ struct fan_fsid * fsid )
12001257{
12011258 struct ucounts * ucounts = group -> fanotify_data .ucounts ;
1259+ struct fanotify_mark * fan_mark ;
12021260 struct fsnotify_mark * mark ;
12031261 int ret ;
12041262
@@ -1211,24 +1269,34 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
12111269 !inc_ucount (ucounts -> ns , ucounts -> uid , UCOUNT_FANOTIFY_MARKS ))
12121270 return ERR_PTR (- ENOSPC );
12131271
1214- mark = kmem_cache_alloc (fanotify_mark_cache , GFP_KERNEL );
1215- if (!mark ) {
1272+ fan_mark = kmem_cache_alloc (fanotify_mark_cache , GFP_KERNEL );
1273+ if (!fan_mark ) {
12161274 ret = - ENOMEM ;
12171275 goto out_dec_ucounts ;
12181276 }
12191277
1278+ mark = & fan_mark -> fsn_mark ;
12201279 fsnotify_init_mark (mark , group );
12211280 if (fan_flags & FAN_MARK_EVICTABLE )
12221281 mark -> flags |= FSNOTIFY_MARK_FLAG_NO_IREF ;
12231282
1224- ret = fsnotify_add_mark_locked (mark , connp , obj_type , 0 , fsid );
1225- if (ret ) {
1226- fsnotify_put_mark (mark );
1227- goto out_dec_ucounts ;
1283+ /* Cache fsid of filesystem containing the marked object */
1284+ if (fsid ) {
1285+ ret = fanotify_set_mark_fsid (group , mark , fsid );
1286+ if (ret )
1287+ goto out_put_mark ;
1288+ } else {
1289+ fan_mark -> fsid .val [0 ] = fan_mark -> fsid .val [1 ] = 0 ;
12281290 }
12291291
1292+ ret = fsnotify_add_mark_locked (mark , connp , obj_type , 0 );
1293+ if (ret )
1294+ goto out_put_mark ;
1295+
12301296 return mark ;
12311297
1298+ out_put_mark :
1299+ fsnotify_put_mark (mark );
12321300out_dec_ucounts :
12331301 if (!FAN_GROUP_FLAG (group , FAN_UNLIMITED_MARKS ))
12341302 dec_ucount (ucounts , UCOUNT_FANOTIFY_MARKS );
@@ -1279,7 +1347,7 @@ static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
12791347static int fanotify_add_mark (struct fsnotify_group * group ,
12801348 fsnotify_connp_t * connp , unsigned int obj_type ,
12811349 __u32 mask , unsigned int fan_flags ,
1282- __kernel_fsid_t * fsid )
1350+ struct fan_fsid * fsid )
12831351{
12841352 struct fsnotify_mark * fsn_mark ;
12851353 bool recalc ;
@@ -1327,23 +1395,23 @@ static int fanotify_add_mark(struct fsnotify_group *group,
13271395
13281396static int fanotify_add_vfsmount_mark (struct fsnotify_group * group ,
13291397 struct vfsmount * mnt , __u32 mask ,
1330- unsigned int flags , __kernel_fsid_t * fsid )
1398+ unsigned int flags , struct fan_fsid * fsid )
13311399{
13321400 return fanotify_add_mark (group , & real_mount (mnt )-> mnt_fsnotify_marks ,
13331401 FSNOTIFY_OBJ_TYPE_VFSMOUNT , mask , flags , fsid );
13341402}
13351403
13361404static int fanotify_add_sb_mark (struct fsnotify_group * group ,
13371405 struct super_block * sb , __u32 mask ,
1338- unsigned int flags , __kernel_fsid_t * fsid )
1406+ unsigned int flags , struct fan_fsid * fsid )
13391407{
13401408 return fanotify_add_mark (group , & sb -> s_fsnotify_marks ,
13411409 FSNOTIFY_OBJ_TYPE_SB , mask , flags , fsid );
13421410}
13431411
13441412static int fanotify_add_inode_mark (struct fsnotify_group * group ,
13451413 struct inode * inode , __u32 mask ,
1346- unsigned int flags , __kernel_fsid_t * fsid )
1414+ unsigned int flags , struct fan_fsid * fsid )
13471415{
13481416 pr_debug ("%s: group=%p inode=%p\n" , __func__ , group , inode );
13491417
@@ -1554,20 +1622,25 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
15541622 return fd ;
15551623}
15561624
1557- static int fanotify_test_fsid (struct dentry * dentry , __kernel_fsid_t * fsid )
1625+ static int fanotify_test_fsid (struct dentry * dentry , unsigned int flags ,
1626+ struct fan_fsid * fsid )
15581627{
1628+ unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
15591629 __kernel_fsid_t root_fsid ;
15601630 int err ;
15611631
15621632 /*
15631633 * Make sure dentry is not of a filesystem with zero fsid (e.g. fuse).
15641634 */
1565- err = vfs_get_fsid (dentry , fsid );
1635+ err = vfs_get_fsid (dentry , & fsid -> id );
15661636 if (err )
15671637 return err ;
15681638
1569- if (!fsid -> val [0 ] && !fsid -> val [1 ])
1570- return - ENODEV ;
1639+ fsid -> sb = dentry -> d_sb ;
1640+ if (!fsid -> id .val [0 ] && !fsid -> id .val [1 ]) {
1641+ err = - ENODEV ;
1642+ goto weak ;
1643+ }
15711644
15721645 /*
15731646 * Make sure dentry is not of a filesystem subvolume (e.g. btrfs)
@@ -1577,11 +1650,18 @@ static int fanotify_test_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
15771650 if (err )
15781651 return err ;
15791652
1580- if (root_fsid .val [0 ] != fsid -> val [0 ] ||
1581- root_fsid .val [1 ] != fsid -> val [1 ])
1582- return - EXDEV ;
1653+ if (!fanotify_fsid_equal (& root_fsid , & fsid -> id )) {
1654+ err = - EXDEV ;
1655+ goto weak ;
1656+ }
15831657
1658+ fsid -> weak = false;
15841659 return 0 ;
1660+
1661+ weak :
1662+ /* Allow weak fsid when marking inodes */
1663+ fsid -> weak = true;
1664+ return (mark_type == FAN_MARK_INODE ) ? 0 : err ;
15851665}
15861666
15871667/* Check if filesystem can encode a unique fid */
@@ -1665,7 +1745,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
16651745 struct fsnotify_group * group ;
16661746 struct fd f ;
16671747 struct path path ;
1668- __kernel_fsid_t __fsid , * fsid = NULL ;
1748+ struct fan_fsid __fsid , * fsid = NULL ;
16691749 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS ;
16701750 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
16711751 unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS ;
@@ -1817,7 +1897,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18171897 }
18181898
18191899 if (fid_mode ) {
1820- ret = fanotify_test_fsid (path .dentry , & __fsid );
1900+ ret = fanotify_test_fsid (path .dentry , flags , & __fsid );
18211901 if (ret )
18221902 goto path_put_and_out ;
18231903
@@ -1935,7 +2015,7 @@ static int __init fanotify_user_setup(void)
19352015 BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) != 12 );
19362016 BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_MARK_FLAGS ) != 11 );
19372017
1938- fanotify_mark_cache = KMEM_CACHE (fsnotify_mark ,
2018+ fanotify_mark_cache = KMEM_CACHE (fanotify_mark ,
19392019 SLAB_PANIC |SLAB_ACCOUNT );
19402020 fanotify_fid_event_cachep = KMEM_CACHE (fanotify_fid_event ,
19412021 SLAB_PANIC );
0 commit comments