History

Merge tag 'fsnotify_for_v5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify updates from Jan Kara: - support for FAN_MARK_IGNORE which untangles some of the not well defined corner cases with fanotify ignore masks - small cleanups * tag 'fsnotify_for_v5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: Fix comment typo fanotify: introduce FAN_MARK_IGNORE fanotify: cleanups for fanotify_mark() input validations fanotify: prepare for setting event flags in ignore mask fs: inotify: Fix typo in inotify comment

Linus Torvalds committed 4 years ago

Commit bec14d72 parents af07685 feee1ce9 files · +214 −59Browse files

Unified · Split

9 files
  1. fs/notify/fanotify/fanotify.c +11 −8
  2. fs/notify/fanotify/fanotify.h +2 −0
  3. fs/notify/fanotify/fanotify_user.c +84 −26
  4. fs/notify/fdinfo.c +3 −3
  5. fs/notify/fsnotify.c +13 −10
  6. fs/notify/inotify/inotify_user.c +1 −1
  7. include/linux/fanotify.h +9 −5
  8. include/linux/fsnotify_backend.h +83 −6
  9. include/uapi/linux/fanotify.h +8 −0
fs/notify/fanotify/fanotify.c+11−8
@@ -295,12 +295,13 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, · 294 unmodified lines
295 const void *data, int data_type,295 const void *data, int data_type,
296 struct inode *dir)296 struct inode *dir)
297{297{
298 __u32 marks_mask = 0, marks_ignored_mask = 0;298 __u32 marks_mask = 0, marks_ignore_mask = 0;
299 __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS |299 __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS |
300 FANOTIFY_EVENT_FLAGS;300 FANOTIFY_EVENT_FLAGS;
301 const struct path *path = fsnotify_data_path(data, data_type);301 const struct path *path = fsnotify_data_path(data, data_type);
302 unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);302 unsigned int fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
303 struct fsnotify_mark *mark;303 struct fsnotify_mark *mark;
304 bool ondir = event_mask & FAN_ONDIR;
304 int type;305 int type;
305 306
306 pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",307 pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
@@ -315,19 +316,21 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, · 8 unmodified lines
315 return 0;316 return 0;
316 } else if (!(fid_mode & FAN_REPORT_FID)) {317 } else if (!(fid_mode & FAN_REPORT_FID)) {
317 /* Do we have a directory inode to report? */318 /* Do we have a directory inode to report? */
318 if (!dir && !(event_mask & FS_ISDIR))319 if (!dir && !ondir)
319 return 0;320 return 0;
320 }321 }
321 322
322 fsnotify_foreach_iter_mark_type(iter_info, mark, type) {323 fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
323 /* Apply ignore mask regardless of mark's ISDIR flag */324 /*
324 marks_ignored_mask |= mark->ignored_mask;325 * Apply ignore mask depending on event flags in ignore mask.
326 */
327 marks_ignore_mask |=
328 fsnotify_effective_ignore_mask(mark, ondir, type);
325 329
326 /*330 /*
327 * If the event is on dir and this mark doesn't care about331 * Send the event depending on event flags in mark mask.
328 * events on dir, don't send it!
329 */332 */
330 if (event_mask & FS_ISDIR && !(mark->mask & FS_ISDIR))333 if (!fsnotify_mask_applicable(mark->mask, ondir, type))
331 continue;334 continue;
332 335
333 marks_mask |= mark->mask;336 marks_mask |= mark->mask;
@@ -336,7 +339,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, · 2 unmodified lines
336 *match_mask |= 1U << type;339 *match_mask |= 1U << type;
337 }340 }
338 341
339 test_mask = event_mask & marks_mask & ~marks_ignored_mask;342 test_mask = event_mask & marks_mask & ~marks_ignore_mask;
340 343
341 /*344 /*
342 * For dirent modification events (create/delete/move) that do not carry345 * For dirent modification events (create/delete/move) that do not carry
fs/notify/fanotify/fanotify.h+2−0
@@ -499,6 +499,8 @@ static inline unsigned int fanotify_mark_user_flags(struct fsnotify_mark *mark) · 498 unmodified lines
499 mflags |= FAN_MARK_IGNORED_SURV_MODIFY;499 mflags |= FAN_MARK_IGNORED_SURV_MODIFY;
500 if (mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF)500 if (mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF)
501 mflags |= FAN_MARK_EVICTABLE;501 mflags |= FAN_MARK_EVICTABLE;
502 if (mark->flags & FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS)
503 mflags |= FAN_MARK_IGNORE;
502 504
503 return mflags;505 return mflags;
504}506}
fs/notify/fanotify/fanotify_user.c+84−26
@@ -1009,10 +1009,10 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, · 1008 unmodified lines
1009 mask &= ~umask;1009 mask &= ~umask;
1010 spin_lock(&fsn_mark->lock);1010 spin_lock(&fsn_mark->lock);
1011 oldmask = fsnotify_calc_mask(fsn_mark);1011 oldmask = fsnotify_calc_mask(fsn_mark);
1012 if (!(flags & FAN_MARK_IGNORED_MASK)) {1012 if (!(flags & FANOTIFY_MARK_IGNORE_BITS)) {
1013 fsn_mark->mask &= ~mask;1013 fsn_mark->mask &= ~mask;
1014 } else {1014 } else {
1015 fsn_mark->ignored_mask &= ~mask;1015 fsn_mark->ignore_mask &= ~mask;
1016 }1016 }
1017 newmask = fsnotify_calc_mask(fsn_mark);1017 newmask = fsnotify_calc_mask(fsn_mark);
1018 /*1018 /*
@@ -1021,7 +1021,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, · 2 unmodified lines
1021 * changes to the mask.1021 * changes to the mask.
1022 * Destroy mark when only umask bits remain.1022 * Destroy mark when only umask bits remain.
1023 */1023 */
1024 *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask);1024 *destroy = !((fsn_mark->mask | fsn_mark->ignore_mask) & ~umask);
1025 spin_unlock(&fsn_mark->lock);1025 spin_unlock(&fsn_mark->lock);
1026 1026
1027 return oldmask & ~newmask;1027 return oldmask & ~newmask;
@@ -1085,15 +1085,24 @@ static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark, · 57 unmodified lines
1085 unsigned int fan_flags)1085 unsigned int fan_flags)
1086{1086{
1087 bool want_iref = !(fan_flags & FAN_MARK_EVICTABLE);1087 bool want_iref = !(fan_flags & FAN_MARK_EVICTABLE);
1088 unsigned int ignore = fan_flags & FANOTIFY_MARK_IGNORE_BITS;
1088 bool recalc = false;1089 bool recalc = false;
1089 1090
1091 /*
1092 * When using FAN_MARK_IGNORE for the first time, mark starts using
1093 * independent event flags in ignore mask. After that, trying to
1094 * update the ignore mask with the old FAN_MARK_IGNORED_MASK API
1095 * will result in EEXIST error.
1096 */
1097 if (ignore == FAN_MARK_IGNORE)
1098 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS;
1099
1090 /*1100 /*
1091 * Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time may lead to1101 * Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time may lead to
1092 * the removal of the FS_MODIFY bit in calculated mask if it was set1102 * the removal of the FS_MODIFY bit in calculated mask if it was set
1093 * because of an ignored mask that is now going to survive FS_MODIFY.1103 * because of an ignore mask that is now going to survive FS_MODIFY.
1094 */1104 */
1095 if ((fan_flags & FAN_MARK_IGNORED_MASK) &&1105 if (ignore && (fan_flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
1096 (fan_flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
1097 !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) {1106 !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) {
1098 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;1107 fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
1099 if (!(fsn_mark->mask & FS_MODIFY))1108 if (!(fsn_mark->mask & FS_MODIFY))
@@ -1120,10 +1129,10 @@ static bool fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, · 20 unmodified lines
1120 bool recalc;1129 bool recalc;
1121 1130
1122 spin_lock(&fsn_mark->lock);1131 spin_lock(&fsn_mark->lock);
1123 if (!(fan_flags & FAN_MARK_IGNORED_MASK))1132 if (!(fan_flags & FANOTIFY_MARK_IGNORE_BITS))
1124 fsn_mark->mask |= mask;1133 fsn_mark->mask |= mask;
1125 else1134 else
1126 fsn_mark->ignored_mask |= mask;1135 fsn_mark->ignore_mask |= mask;
1127 1136
1128 recalc = fsnotify_calc_mask(fsn_mark) &1137 recalc = fsnotify_calc_mask(fsn_mark) &
1129 ~fsnotify_conn_mask(fsn_mark->connector);1138 ~fsnotify_conn_mask(fsn_mark->connector);
@@ -1187,6 +1196,37 @@ static int fanotify_group_init_error_pool(struct fsnotify_group *group) · 57 unmodified lines
1187 sizeof(struct fanotify_error_event));1196 sizeof(struct fanotify_error_event));
1188}1197}
1189 1198
1199static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
1200 unsigned int fan_flags)
1201{
1202 /*
1203 * Non evictable mark cannot be downgraded to evictable mark.
1204 */
1205 if (fan_flags & FAN_MARK_EVICTABLE &&
1206 !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF))
1207 return -EEXIST;
1208
1209 /*
1210 * New ignore mask semantics cannot be downgraded to old semantics.
1211 */
1212 if (fan_flags & FAN_MARK_IGNORED_MASK &&
1213 fsn_mark->flags & FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS)
1214 return -EEXIST;
1215
1216 /*
1217 * An ignore mask that survives modify could never be downgraded to not
1218 * survive modify. With new FAN_MARK_IGNORE semantics we make that rule
1219 * explicit and return an error when trying to update the ignore mask
1220 * without the original FAN_MARK_IGNORED_SURV_MODIFY value.
1221 */
1222 if (fan_flags & FAN_MARK_IGNORE &&
1223 !(fan_flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
1224 fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)
1225 return -EEXIST;
1226
1227 return 0;
1228}
1229
1190static int fanotify_add_mark(struct fsnotify_group *group,1230static int fanotify_add_mark(struct fsnotify_group *group,
1191 fsnotify_connp_t *connp, unsigned int obj_type,1231 fsnotify_connp_t *connp, unsigned int obj_type,
1192 __u32 mask, unsigned int fan_flags,1232 __u32 mask, unsigned int fan_flags,
@@ -1208,19 +1248,18 @@ static int fanotify_add_mark(struct fsnotify_group *group, · 15 unmodified lines
1208 }1248 }
1209 1249
1210 /*1250 /*
1211 * Non evictable mark cannot be downgraded to evictable mark.1251 * Check if requested mark flags conflict with an existing mark flags.
1212 */1252 */
1213 if (fan_flags & FAN_MARK_EVICTABLE &&1253 ret = fanotify_may_update_existing_mark(fsn_mark, fan_flags);
1214 !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF)) {1254 if (ret)
1215 ret = -EEXIST;
1216 goto out;1255 goto out;
1217 }
1218 1256
1219 /*1257 /*
1220 * Error events are pre-allocated per group, only if strictly1258 * Error events are pre-allocated per group, only if strictly
1221 * needed (i.e. FAN_FS_ERROR was requested).1259 * needed (i.e. FAN_FS_ERROR was requested).
1222 */1260 */
1223 if (!(fan_flags & FAN_MARK_IGNORED_MASK) && (mask & FAN_FS_ERROR)) {1261 if (!(fan_flags & FANOTIFY_MARK_IGNORE_BITS) &&
1262 (mask & FAN_FS_ERROR)) {
1224 ret = fanotify_group_init_error_pool(group);1263 ret = fanotify_group_init_error_pool(group);
1225 if (ret)1264 if (ret)
1226 goto out;1265 goto out;
@@ -1261,10 +1300,10 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group, · 34 unmodified lines
1261 1300
1262 /*1301 /*
1263 * If some other task has this inode open for write we should not add1302 * If some other task has this inode open for write we should not add
1264 * an ignored mark, unless that ignored mark is supposed to survive1303 * an ignore mask, unless that ignore mask is supposed to survive
1265 * modification changes anyway.1304 * modification changes anyway.
1266 */1305 */
1267 if ((flags & FAN_MARK_IGNORED_MASK) &&1306 if ((flags & FANOTIFY_MARK_IGNORE_BITS) &&
1268 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&1307 !(flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
1269 inode_is_open_for_write(inode))1308 inode_is_open_for_write(inode))
1270 return 0;1309 return 0;
@@ -1520,7 +1559,8 @@ static int fanotify_events_supported(struct fsnotify_group *group, · 249 unmodified lines
1520 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;1559 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
1521 /* Strict validation of events in non-dir inode mask with v5.17+ APIs */1560 /* Strict validation of events in non-dir inode mask with v5.17+ APIs */
1522 bool strict_dir_events = FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID) ||1561 bool strict_dir_events = FAN_GROUP_FLAG(group, FAN_REPORT_TARGET_FID) ||
1523 (mask & FAN_RENAME);1562 (mask & FAN_RENAME) ||
1563 (flags & FAN_MARK_IGNORE);
1524 1564
1525 /*1565 /*
1526 * Some filesystems such as 'proc' acquire unusual locks when opening1566 * Some filesystems such as 'proc' acquire unusual locks when opening
@@ -1557,7 +1597,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 30 unmodified lines
1557 __kernel_fsid_t __fsid, *fsid = NULL;1597 __kernel_fsid_t __fsid, *fsid = NULL;
1558 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;1598 u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
1559 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;1599 unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
1560 bool ignored = flags & FAN_MARK_IGNORED_MASK;1600 unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS;
1601 unsigned int ignore = flags & FANOTIFY_MARK_IGNORE_BITS;
1561 unsigned int obj_type, fid_mode;1602 unsigned int obj_type, fid_mode;
1562 u32 umask = 0;1603 u32 umask = 0;
1563 int ret;1604 int ret;
@@ -1586,7 +1627,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 22 unmodified lines
1586 return -EINVAL;1627 return -EINVAL;
1587 }1628 }
1588 1629
1589 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {1630 switch (mark_cmd) {
1590 case FAN_MARK_ADD:1631 case FAN_MARK_ADD:
1591 case FAN_MARK_REMOVE:1632 case FAN_MARK_REMOVE:
1592 if (!mask)1633 if (!mask)
@@ -1606,9 +1647,19 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 13 unmodified lines
1606 if (mask & ~valid_mask)1647 if (mask & ~valid_mask)
1607 return -EINVAL;1648 return -EINVAL;
1608 1649
1609 /* Event flags (ONDIR, ON_CHILD) are meaningless in ignored mask */1650
1610 if (ignored)1651 /* We don't allow FAN_MARK_IGNORE & FAN_MARK_IGNORED_MASK together */
1652 if (ignore == (FAN_MARK_IGNORE | FAN_MARK_IGNORED_MASK))
1653 return -EINVAL;
1654
1655 /*
1656 * Event flags (FAN_ONDIR, FAN_EVENT_ON_CHILD) have no effect with
1657 * FAN_MARK_IGNORED_MASK.
1658 */
1659 if (ignore == FAN_MARK_IGNORED_MASK) {
1611 mask &= ~FANOTIFY_EVENT_FLAGS;1660 mask &= ~FANOTIFY_EVENT_FLAGS;
1661 umask = FANOTIFY_EVENT_FLAGS;
1662 }
1612 1663
1613 f = fdget(fanotify_fd);1664 f = fdget(fanotify_fd);
1614 if (unlikely(!f.file))1665 if (unlikely(!f.file))
@@ -1672,7 +1723,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 57 unmodified lines
1672 if (mask & FAN_RENAME && !(fid_mode & FAN_REPORT_NAME))1723 if (mask & FAN_RENAME && !(fid_mode & FAN_REPORT_NAME))
1673 goto fput_and_out;1724 goto fput_and_out;
1674 1725
1675 if (flags & FAN_MARK_FLUSH) {1726 if (mark_cmd == FAN_MARK_FLUSH) {
1676 ret = 0;1727 ret = 0;
1677 if (mark_type == FAN_MARK_MOUNT)1728 if (mark_type == FAN_MARK_MOUNT)
1678 fsnotify_clear_vfsmount_marks_by_group(group);1729 fsnotify_clear_vfsmount_marks_by_group(group);
@@ -1688,7 +1739,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 9 unmodified lines
1688 if (ret)1739 if (ret)
1689 goto fput_and_out;1740 goto fput_and_out;
1690 1741
1691 if (flags & FAN_MARK_ADD) {1742 if (mark_cmd == FAN_MARK_ADD) {
1692 ret = fanotify_events_supported(group, &path, mask, flags);1743 ret = fanotify_events_supported(group, &path, mask, flags);
1693 if (ret)1744 if (ret)
1694 goto path_put_and_out;1745 goto path_put_and_out;
@@ -1712,6 +1763,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 17 unmodified lines
1712 else1763 else
1713 mnt = path.mnt;1764 mnt = path.mnt;
1714 1765
1766 ret = mnt ? -EINVAL : -EISDIR;
1767 /* FAN_MARK_IGNORE requires SURV_MODIFY for sb/mount/dir marks */
1768 if (mark_cmd == FAN_MARK_ADD && ignore == FAN_MARK_IGNORE &&
1769 (mnt || S_ISDIR(inode->i_mode)) &&
1770 !(flags & FAN_MARK_IGNORED_SURV_MODIFY))
1771 goto path_put_and_out;
1772
1715 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */1773 /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */
1716 if (mnt || !S_ISDIR(inode->i_mode)) {1774 if (mnt || !S_ISDIR(inode->i_mode)) {
1717 mask &= ~FAN_EVENT_ON_CHILD;1775 mask &= ~FAN_EVENT_ON_CHILD;
@@ -1721,12 +1779,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, · 3 unmodified lines
1721 * events with parent/name info for non-directory.1779 * events with parent/name info for non-directory.
1722 */1780 */
1723 if ((fid_mode & FAN_REPORT_DIR_FID) &&1781 if ((fid_mode & FAN_REPORT_DIR_FID) &&
1724 (flags & FAN_MARK_ADD) && !ignored)1782 (flags & FAN_MARK_ADD) && !ignore)
1725 mask |= FAN_EVENT_ON_CHILD;1783 mask |= FAN_EVENT_ON_CHILD;
1726 }1784 }
1727 1785
1728 /* create/update an inode mark */1786 /* create/update an inode mark */
1729 switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {1787 switch (mark_cmd) {
1730 case FAN_MARK_ADD:1788 case FAN_MARK_ADD:
1731 if (mark_type == FAN_MARK_MOUNT)1789 if (mark_type == FAN_MARK_MOUNT)
1732 ret = fanotify_add_vfsmount_mark(group, mnt, mask,1790 ret = fanotify_add_vfsmount_mark(group, mnt, mask,
@@ -1804,7 +1862,7 @@ static int __init fanotify_user_setup(void) · 71 unmodified lines
1804 1862
1805 BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);1863 BUILD_BUG_ON(FANOTIFY_INIT_FLAGS & FANOTIFY_INTERNAL_GROUP_FLAGS);
1806 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 12);1864 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 12);
1807 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 10);1865 BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 11);
1808 1866
1809 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,1867 fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
1810 SLAB_PANIC|SLAB_ACCOUNT);1868 SLAB_PANIC|SLAB_ACCOUNT);
fs/notify/fdinfo.c+3−3
@@ -113,7 +113,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) · 112 unmodified lines
113 return;113 return;
114 seq_printf(m, "fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x ",114 seq_printf(m, "fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x ",
115 inode->i_ino, inode->i_sb->s_dev,115 inode->i_ino, inode->i_sb->s_dev,
116 mflags, mark->mask, mark->ignored_mask);116 mflags, mark->mask, mark->ignore_mask);
117 show_mark_fhandle(m, inode);117 show_mark_fhandle(m, inode);
118 seq_putc(m, '\n');118 seq_putc(m, '\n');
119 iput(inode);119 iput(inode);
@@ -121,12 +121,12 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) · 1 unmodified line
121 struct mount *mnt = fsnotify_conn_mount(mark->connector);121 struct mount *mnt = fsnotify_conn_mount(mark->connector);
122 122
123 seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",123 seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",
124 mnt->mnt_id, mflags, mark->mask, mark->ignored_mask);124 mnt->mnt_id, mflags, mark->mask, mark->ignore_mask);
125 } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_SB) {125 } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_SB) {
126 struct super_block *sb = fsnotify_conn_sb(mark->connector);126 struct super_block *sb = fsnotify_conn_sb(mark->connector);
127 127
128 seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n",128 seq_printf(m, "fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n",
129 sb->s_dev, mflags, mark->mask, mark->ignored_mask);129 sb->s_dev, mflags, mark->mask, mark->ignore_mask);
130 }130 }
131}131}
132 132
fs/notify/fsnotify.c+13−10
@@ -100,7 +100,7 @@ void fsnotify_sb_delete(struct super_block *sb) · 99 unmodified lines
100 * Given an inode, first check if we care what happens to our children. Inotify100 * Given an inode, first check if we care what happens to our children. Inotify
101 * and dnotify both tell their parents about events. If we care about any event101 * and dnotify both tell their parents about events. If we care about any event
102 * on a child we run all of our children and set a dentry flag saying that the102 * on a child we run all of our children and set a dentry flag saying that the
103 * parent cares. Thus when an event happens on a child it can quickly tell if103 * parent cares. Thus when an event happens on a child it can quickly tell
104 * if there is a need to find a parent and send the event to the parent.104 * if there is a need to find a parent and send the event to the parent.
105 */105 */
106void __fsnotify_update_child_dentry_flags(struct inode *inode)106void __fsnotify_update_child_dentry_flags(struct inode *inode)
@@ -324,7 +324,8 @@ static int send_to_group(__u32 mask, const void *data, int data_type, · 217 unmodified lines
324 struct fsnotify_group *group = NULL;324 struct fsnotify_group *group = NULL;
325 __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);325 __u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
326 __u32 marks_mask = 0;326 __u32 marks_mask = 0;
327 __u32 marks_ignored_mask = 0;327 __u32 marks_ignore_mask = 0;
328 bool is_dir = mask & FS_ISDIR;
328 struct fsnotify_mark *mark;329 struct fsnotify_mark *mark;
329 int type;330 int type;
330 331
@@ -336,7 +337,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type, · 5 unmodified lines
336 fsnotify_foreach_iter_mark_type(iter_info, mark, type) {337 fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
337 if (!(mark->flags &338 if (!(mark->flags &
338 FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))339 FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
339 mark->ignored_mask = 0;340 mark->ignore_mask = 0;
340 }341 }
341 }342 }
342 343
@@ -344,14 +345,15 @@ static int send_to_group(__u32 mask, const void *data, int data_type, · 1 unmodified line
344 fsnotify_foreach_iter_mark_type(iter_info, mark, type) {345 fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
345 group = mark->group;346 group = mark->group;
346 marks_mask |= mark->mask;347 marks_mask |= mark->mask;
347 marks_ignored_mask |= mark->ignored_mask;348 marks_ignore_mask |=
349 fsnotify_effective_ignore_mask(mark, is_dir, type);
348 }350 }
349 351
350 pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",352 pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignore_mask=%x data=%p data_type=%d dir=%p cookie=%d\n",
351 __func__, group, mask, marks_mask, marks_ignored_mask,353 __func__, group, mask, marks_mask, marks_ignore_mask,
352 data, data_type, dir, cookie);354 data, data_type, dir, cookie);
353 355
354 if (!(test_mask & marks_mask & ~marks_ignored_mask))356 if (!(test_mask & marks_mask & ~marks_ignore_mask))
355 return 0;357 return 0;
356 358
357 if (group->ops->handle_event) {359 if (group->ops->handle_event) {
@@ -423,7 +425,8 @@ static bool fsnotify_iter_select_report_types( · 65 unmodified lines
423 * But is *this mark* watching children?425 * But is *this mark* watching children?
424 */426 */
425 if (type == FSNOTIFY_ITER_TYPE_PARENT &&427 if (type == FSNOTIFY_ITER_TYPE_PARENT &&
426 !(mark->mask & FS_EVENT_ON_CHILD))428 !(mark->mask & FS_EVENT_ON_CHILD) &&
429 !(fsnotify_ignore_mask(mark) & FS_EVENT_ON_CHILD))
427 continue;430 continue;
428 431
429 fsnotify_iter_set_report_type(iter_info, type);432 fsnotify_iter_set_report_type(iter_info, type);
@@ -532,8 +535,8 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 102 unmodified lines
532 535
533 536
534 /*537 /*
535 * If this is a modify event we may need to clear some ignored masks.538 * If this is a modify event we may need to clear some ignore masks.
536 * In that case, the object with ignored masks will have the FS_MODIFY539 * In that case, the object with ignore masks will have the FS_MODIFY
537 * event in its mask.540 * event in its mask.
538 * Otherwise, return if none of the marks care about this type of event.541 * Otherwise, return if none of the marks care about this type of event.
539 */542 */
fs/notify/inotify/inotify_user.c+1−1
@@ -136,7 +136,7 @@ static inline u32 inotify_mask_to_arg(__u32 mask) · 135 unmodified lines
136 IN_Q_OVERFLOW);136 IN_Q_OVERFLOW);
137}137}
138 138
139/* intofiy userspace file descriptor functions */139/* inotify userspace file descriptor functions */
140static __poll_t inotify_poll(struct file *file, poll_table *wait)140static __poll_t inotify_poll(struct file *file, poll_table *wait)
141{141{
142 struct fsnotify_group *group = file->private_data;142 struct fsnotify_group *group = file->private_data;
include/linux/fanotify.h+9−5
@@ -59,15 +59,19 @@ · 58 unmodified lines
59#define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \59#define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \
60 FAN_MARK_FILESYSTEM)60 FAN_MARK_FILESYSTEM)
61 61
62#define FANOTIFY_MARK_CMD_BITS (FAN_MARK_ADD | FAN_MARK_REMOVE | \
63 FAN_MARK_FLUSH)
64
65#define FANOTIFY_MARK_IGNORE_BITS (FAN_MARK_IGNORED_MASK | \
66 FAN_MARK_IGNORE)
67
62#define FANOTIFY_MARK_FLAGS (FANOTIFY_MARK_TYPE_BITS | \68#define FANOTIFY_MARK_FLAGS (FANOTIFY_MARK_TYPE_BITS | \
63 FAN_MARK_ADD | \69 FANOTIFY_MARK_CMD_BITS | \
64 FAN_MARK_REMOVE | \70 FANOTIFY_MARK_IGNORE_BITS | \
65 FAN_MARK_DONT_FOLLOW | \71 FAN_MARK_DONT_FOLLOW | \
66 FAN_MARK_ONLYDIR | \72 FAN_MARK_ONLYDIR | \
67 FAN_MARK_IGNORED_MASK | \
68 FAN_MARK_IGNORED_SURV_MODIFY | \73 FAN_MARK_IGNORED_SURV_MODIFY | \
69 FAN_MARK_EVICTABLE | \74 FAN_MARK_EVICTABLE)
70 FAN_MARK_FLUSH)
71 75
72/*76/*
73 * Events that can be reported with data type FSNOTIFY_EVENT_PATH.77 * Events that can be reported with data type FSNOTIFY_EVENT_PATH.
include/linux/fsnotify_backend.h+83−6
@@ -518,8 +518,8 @@ struct fsnotify_mark { · 517 unmodified lines
518 struct hlist_node obj_list;518 struct hlist_node obj_list;
519 /* Head of list of marks for an object [mark ref] */519 /* Head of list of marks for an object [mark ref] */
520 struct fsnotify_mark_connector *connector;520 struct fsnotify_mark_connector *connector;
521 /* Events types to ignore [mark->lock, group->mark_mutex] */521 /* Events types and flags to ignore [mark->lock, group->mark_mutex] */
522 __u32 ignored_mask;522 __u32 ignore_mask;
523 /* General fsnotify mark flags */523 /* General fsnotify mark flags */
524#define FSNOTIFY_MARK_FLAG_ALIVE 0x0001524#define FSNOTIFY_MARK_FLAG_ALIVE 0x0001
525#define FSNOTIFY_MARK_FLAG_ATTACHED 0x0002525#define FSNOTIFY_MARK_FLAG_ATTACHED 0x0002
@@ -529,6 +529,7 @@ struct fsnotify_mark { · 3 unmodified lines
529 /* fanotify mark flags */529 /* fanotify mark flags */
530#define FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY 0x0100530#define FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY 0x0100
531#define FSNOTIFY_MARK_FLAG_NO_IREF 0x0200531#define FSNOTIFY_MARK_FLAG_NO_IREF 0x0200
532#define FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS 0x0400
532 unsigned int flags; /* flags [mark->lock] */533 unsigned int flags; /* flags [mark->lock] */
533};534};
534 535
@@ -655,15 +656,91 @@ extern void fsnotify_remove_queued_event(struct fsnotify_group *group, · 120 unmodified lines
655 656
656/* functions used to manipulate the marks attached to inodes */657/* functions used to manipulate the marks attached to inodes */
657 658
658/* Get mask for calculating object interest taking ignored mask into account */659/*
660 * Canonical "ignore mask" including event flags.
661 *
662 * Note the subtle semantic difference from the legacy ->ignored_mask.
663 * ->ignored_mask traditionally only meant which events should be ignored,
664 * while ->ignore_mask also includes flags regarding the type of objects on
665 * which events should be ignored.
666 */
667static inline __u32 fsnotify_ignore_mask(struct fsnotify_mark *mark)
668{
669 __u32 ignore_mask = mark->ignore_mask;
670
671 /* The event flags in ignore mask take effect */
672 if (mark->flags & FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS)
673 return ignore_mask;
674
675 /*
676 * Legacy behavior:
677 * - Always ignore events on dir
678 * - Ignore events on child if parent is watching children
679 */
680 ignore_mask |= FS_ISDIR;
681 ignore_mask &= ~FS_EVENT_ON_CHILD;
682 ignore_mask |= mark->mask & FS_EVENT_ON_CHILD;
683
684 return ignore_mask;
685}
686
687/* Legacy ignored_mask - only event types to ignore */
688static inline __u32 fsnotify_ignored_events(struct fsnotify_mark *mark)
689{
690 return mark->ignore_mask & ALL_FSNOTIFY_EVENTS;
691}
692
693/*
694 * Check if mask (or ignore mask) should be applied depending if victim is a
695 * directory and whether it is reported to a watching parent.
696 */
697static inline bool fsnotify_mask_applicable(__u32 mask, bool is_dir,
698 int iter_type)
699{
700 /* Should mask be applied to a directory? */
701 if (is_dir && !(mask & FS_ISDIR))
702 return false;
703
704 /* Should mask be applied to a child? */
705 if (iter_type == FSNOTIFY_ITER_TYPE_PARENT &&
706 !(mask & FS_EVENT_ON_CHILD))
707 return false;
708
709 return true;
710}
711
712/*
713 * Effective ignore mask taking into account if event victim is a
714 * directory and whether it is reported to a watching parent.
715 */
716static inline __u32 fsnotify_effective_ignore_mask(struct fsnotify_mark *mark,
717 bool is_dir, int iter_type)
718{
719 __u32 ignore_mask = fsnotify_ignored_events(mark);
720
721 if (!ignore_mask)
722 return 0;
723
724 /* For non-dir and non-child, no need to consult the event flags */
725 if (!is_dir && iter_type != FSNOTIFY_ITER_TYPE_PARENT)
726 return ignore_mask;
727
728 ignore_mask = fsnotify_ignore_mask(mark);
729 if (!fsnotify_mask_applicable(ignore_mask, is_dir, iter_type))
730 return 0;
731
732 return ignore_mask & ALL_FSNOTIFY_EVENTS;
733}
734
735/* Get mask for calculating object interest taking ignore mask into account */
659static inline __u32 fsnotify_calc_mask(struct fsnotify_mark *mark)736static inline __u32 fsnotify_calc_mask(struct fsnotify_mark *mark)
660{737{
661 __u32 mask = mark->mask;738 __u32 mask = mark->mask;
662 739
663 if (!mark->ignored_mask)740 if (!fsnotify_ignored_events(mark))
664 return mask;741 return mask;
665 742
666 /* Interest in FS_MODIFY may be needed for clearing ignored mask */743 /* Interest in FS_MODIFY may be needed for clearing ignore mask */
667 if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))744 if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
668 mask |= FS_MODIFY;745 mask |= FS_MODIFY;
669 746
@@ -671,7 +748,7 @@ static inline __u32 fsnotify_calc_mask(struct fsnotify_mark *mark) · 1 unmodified line
671 * If mark is interested in ignoring events on children, the object must748 * If mark is interested in ignoring events on children, the object must
672 * show interest in those events for fsnotify_parent() to notice it.749 * show interest in those events for fsnotify_parent() to notice it.
673 */750 */
674 return mask | (mark->ignored_mask & ALL_FSNOTIFY_EVENTS);751 return mask | mark->ignore_mask;
675}752}
676 753
677/* Get mask of events for a list of marks */754/* Get mask of events for a list of marks */
include/uapi/linux/fanotify.h+8−0
@@ -83,12 +83,20 @@ · 82 unmodified lines
83#define FAN_MARK_FLUSH 0x0000008083#define FAN_MARK_FLUSH 0x00000080
84/* FAN_MARK_FILESYSTEM is 0x00000100 */84/* FAN_MARK_FILESYSTEM is 0x00000100 */
85#define FAN_MARK_EVICTABLE 0x0000020085#define FAN_MARK_EVICTABLE 0x00000200
86/* This bit is mutually exclusive with FAN_MARK_IGNORED_MASK bit */
87#define FAN_MARK_IGNORE 0x00000400
86 88
87/* These are NOT bitwise flags. Both bits can be used togther. */89/* These are NOT bitwise flags. Both bits can be used togther. */
88#define FAN_MARK_INODE 0x0000000090#define FAN_MARK_INODE 0x00000000
89#define FAN_MARK_MOUNT 0x0000001091#define FAN_MARK_MOUNT 0x00000010
90#define FAN_MARK_FILESYSTEM 0x0000010092#define FAN_MARK_FILESYSTEM 0x00000100
91 93
94/*
95 * Convenience macro - FAN_MARK_IGNORE requires FAN_MARK_IGNORED_SURV_MODIFY
96 * for non-inode mark types.
97 */
98#define FAN_MARK_IGNORE_SURV (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY)
99
92/* Deprecated - do not use this in programs and do not add new flags here! */100/* Deprecated - do not use this in programs and do not add new flags here! */
93#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\101#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
94 FAN_MARK_REMOVE |\102 FAN_MARK_REMOVE |\