@@ -1287,7 +1287,7 @@ static int fanotify_group_init_error_pool(struct fsnotify_group *group)
1287
1287
}
1288
1288
1289
1289
static int fanotify_may_update_existing_mark (struct fsnotify_mark * fsn_mark ,
1290
- unsigned int fan_flags )
1290
+ __u32 mask , unsigned int fan_flags )
1291
1291
{
1292
1292
/*
1293
1293
* Non evictable mark cannot be downgraded to evictable mark.
@@ -1314,6 +1314,11 @@ static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
1314
1314
fsn_mark -> flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY )
1315
1315
return - EEXIST ;
1316
1316
1317
+ /* For now pre-content events are not generated for directories */
1318
+ mask |= fsn_mark -> mask ;
1319
+ if (mask & FANOTIFY_PRE_CONTENT_EVENTS && mask & FAN_ONDIR )
1320
+ return - EEXIST ;
1321
+
1317
1322
return 0 ;
1318
1323
}
1319
1324
@@ -1340,7 +1345,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,
1340
1345
/*
1341
1346
* Check if requested mark flags conflict with an existing mark flags.
1342
1347
*/
1343
- ret = fanotify_may_update_existing_mark (fsn_mark , fan_flags );
1348
+ ret = fanotify_may_update_existing_mark (fsn_mark , mask , fan_flags );
1344
1349
if (ret )
1345
1350
goto out ;
1346
1351
@@ -1640,11 +1645,23 @@ static int fanotify_events_supported(struct fsnotify_group *group,
1640
1645
unsigned int flags )
1641
1646
{
1642
1647
unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS ;
1648
+ bool is_dir = d_is_dir (path -> dentry );
1643
1649
/* Strict validation of events in non-dir inode mask with v5.17+ APIs */
1644
1650
bool strict_dir_events = FAN_GROUP_FLAG (group , FAN_REPORT_TARGET_FID ) ||
1645
1651
(mask & FAN_RENAME ) ||
1646
1652
(flags & FAN_MARK_IGNORE );
1647
1653
1654
+ /*
1655
+ * Filesystems need to opt-into pre-content evnets (a.k.a HSM)
1656
+ * and they are only supported on regular files and directories.
1657
+ */
1658
+ if (mask & FANOTIFY_PRE_CONTENT_EVENTS ) {
1659
+ if (!(path -> mnt -> mnt_sb -> s_iflags & SB_I_ALLOW_HSM ))
1660
+ return - EOPNOTSUPP ;
1661
+ if (!is_dir && !d_is_reg (path -> dentry ))
1662
+ return - EINVAL ;
1663
+ }
1664
+
1648
1665
/*
1649
1666
* Some filesystems such as 'proc' acquire unusual locks when opening
1650
1667
* files. For them fanotify permission events have high chances of
@@ -1677,7 +1694,7 @@ static int fanotify_events_supported(struct fsnotify_group *group,
1677
1694
* but because we always allowed it, error only when using new APIs.
1678
1695
*/
1679
1696
if (strict_dir_events && mark_type == FAN_MARK_INODE &&
1680
- !d_is_dir ( path -> dentry ) && (mask & FANOTIFY_DIRONLY_EVENT_BITS ))
1697
+ !is_dir && (mask & FANOTIFY_DIRONLY_EVENT_BITS ))
1681
1698
return - ENOTDIR ;
1682
1699
1683
1700
return 0 ;
@@ -1778,10 +1795,14 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1778
1795
return - EPERM ;
1779
1796
1780
1797
/*
1781
- * Permission events require minimum priority FAN_CLASS_CONTENT.
1798
+ * Permission events are not allowed for FAN_CLASS_NOTIF.
1799
+ * Pre-content permission events are not allowed for FAN_CLASS_CONTENT.
1782
1800
*/
1783
1801
if (mask & FANOTIFY_PERM_EVENTS &&
1784
- group -> priority < FSNOTIFY_PRIO_CONTENT )
1802
+ group -> priority == FSNOTIFY_PRIO_NORMAL )
1803
+ return - EINVAL ;
1804
+ else if (mask & FANOTIFY_PRE_CONTENT_EVENTS &&
1805
+ group -> priority == FSNOTIFY_PRIO_CONTENT )
1785
1806
return - EINVAL ;
1786
1807
1787
1808
if (mask & FAN_FS_ERROR &&
@@ -1816,6 +1837,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
1816
1837
if (mask & FAN_RENAME && !(fid_mode & FAN_REPORT_NAME ))
1817
1838
return - EINVAL ;
1818
1839
1840
+ /* Pre-content events are not currently generated for directories. */
1841
+ if (mask & FANOTIFY_PRE_CONTENT_EVENTS && mask & FAN_ONDIR )
1842
+ return - EINVAL ;
1843
+
1819
1844
if (mark_cmd == FAN_MARK_FLUSH ) {
1820
1845
if (mark_type == FAN_MARK_MOUNT )
1821
1846
fsnotify_clear_vfsmount_marks_by_group (group );
0 commit comments