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,11 +1192,68 @@ 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 ;
12021259 struct fanotify_mark * fan_mark ;
@@ -1225,20 +1282,21 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
12251282
12261283 /* Cache fsid of filesystem containing the marked object */
12271284 if (fsid ) {
1228- fan_mark -> fsid = * fsid ;
1229- mark -> flags |= FSNOTIFY_MARK_FLAG_HAS_FSID ;
1285+ ret = fanotify_set_mark_fsid (group , mark , fsid );
1286+ if (ret )
1287+ goto out_put_mark ;
12301288 } else {
12311289 fan_mark -> fsid .val [0 ] = fan_mark -> fsid .val [1 ] = 0 ;
12321290 }
12331291
12341292 ret = fsnotify_add_mark_locked (mark , connp , obj_type , 0 );
1235- if (ret ) {
1236- fsnotify_put_mark (mark );
1237- goto out_dec_ucounts ;
1238- }
1293+ if (ret )
1294+ goto out_put_mark ;
12391295
12401296 return mark ;
12411297
1298+ out_put_mark :
1299+ fsnotify_put_mark (mark );
12421300out_dec_ucounts :
12431301 if (!FAN_GROUP_FLAG (group , FAN_UNLIMITED_MARKS ))
12441302 dec_ucount (ucounts , UCOUNT_FANOTIFY_MARKS );
@@ -1289,7 +1347,7 @@ static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
12891347static int fanotify_add_mark (struct fsnotify_group * group ,
12901348 fsnotify_connp_t * connp , unsigned int obj_type ,
12911349 __u32 mask , unsigned int fan_flags ,
1292- __kernel_fsid_t * fsid )
1350+ struct fan_fsid * fsid )
12931351{
12941352 struct fsnotify_mark * fsn_mark ;
12951353 bool recalc ;
@@ -1337,23 +1395,23 @@ static int fanotify_add_mark(struct fsnotify_group *group,
13371395
13381396static int fanotify_add_vfsmount_mark (struct fsnotify_group * group ,
13391397 struct vfsmount * mnt , __u32 mask ,
1340- unsigned int flags , __kernel_fsid_t * fsid )
1398+ unsigned int flags , struct fan_fsid * fsid )
13411399{
13421400 return fanotify_add_mark (group , & real_mount (mnt )-> mnt_fsnotify_marks ,
13431401 FSNOTIFY_OBJ_TYPE_VFSMOUNT , mask , flags , fsid );
13441402}
13451403
13461404static int fanotify_add_sb_mark (struct fsnotify_group * group ,
13471405 struct super_block * sb , __u32 mask ,
1348- unsigned int flags , __kernel_fsid_t * fsid )
1406+ unsigned int flags , struct fan_fsid * fsid )
13491407{
13501408 return fanotify_add_mark (group , & sb -> s_fsnotify_marks ,
13511409 FSNOTIFY_OBJ_TYPE_SB , mask , flags , fsid );
13521410}
13531411
13541412static int fanotify_add_inode_mark (struct fsnotify_group * group ,
13551413 struct inode * inode , __u32 mask ,
1356- unsigned int flags , __kernel_fsid_t * fsid )
1414+ unsigned int flags , struct fan_fsid * fsid )
13571415{
13581416 pr_debug ("%s: group=%p inode=%p\n" , __func__ , group , inode );
13591417
@@ -1564,20 +1622,25 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
15641622 return fd ;
15651623}
15661624
1567- 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 )
15681627{
1628+ unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
15691629 __kernel_fsid_t root_fsid ;
15701630 int err ;
15711631
15721632 /*
15731633 * Make sure dentry is not of a filesystem with zero fsid (e.g. fuse).
15741634 */
1575- err = vfs_get_fsid (dentry , fsid );
1635+ err = vfs_get_fsid (dentry , & fsid -> id );
15761636 if (err )
15771637 return err ;
15781638
1579- if (!fsid -> val [0 ] && !fsid -> val [1 ])
1580- 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+ }
15811644
15821645 /*
15831646 * Make sure dentry is not of a filesystem subvolume (e.g. btrfs)
@@ -1587,11 +1650,18 @@ static int fanotify_test_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
15871650 if (err )
15881651 return err ;
15891652
1590- if (root_fsid .val [0 ] != fsid -> val [0 ] ||
1591- root_fsid .val [1 ] != fsid -> val [1 ])
1592- return - EXDEV ;
1653+ if (!fanotify_fsid_equal (& root_fsid , & fsid -> id )) {
1654+ err = - EXDEV ;
1655+ goto weak ;
1656+ }
15931657
1658+ fsid -> weak = false;
15941659 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 ;
15951665}
15961666
15971667/* Check if filesystem can encode a unique fid */
@@ -1675,7 +1745,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
16751745 struct fsnotify_group * group ;
16761746 struct fd f ;
16771747 struct path path ;
1678- __kernel_fsid_t __fsid , * fsid = NULL ;
1748+ struct fan_fsid __fsid , * fsid = NULL ;
16791749 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS ;
16801750 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
16811751 unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS ;
@@ -1827,7 +1897,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
18271897 }
18281898
18291899 if (fid_mode ) {
1830- ret = fanotify_test_fsid (path .dentry , & __fsid );
1900+ ret = fanotify_test_fsid (path .dentry , flags , & __fsid );
18311901 if (ret )
18321902 goto path_put_and_out ;
18331903
0 commit comments