History

Merge tag 'fsnotify_for_v6.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull fsnotify fixes from Jan Kara: "Fixes for an inotify deadlock and a data race in fsnotify" * tag 'fsnotify_for_v6.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: inotify: Fix possible deadlock in fsnotify_destroy_mark fsnotify: Avoid data race between fsnotify_recalc_mask() and fsnotify_object_watched()

Linus Torvalds committed 2 years ago

Commit e02f08e2 parents 4770119 cad3f4a8 files · +25 −34Browse files

Unified · Split

8 files
  1. fs/nfsd/filecache.c +1 −1
  2. fs/notify/dnotify/dnotify.c +1 −2
  3. fs/notify/fanotify/fanotify_user.c +1 −1
  4. fs/notify/fsnotify.c +12 −9
  5. fs/notify/group.c +0 −11
  6. fs/notify/inotify/inotify_user.c +1 −1
  7. fs/notify/mark.c +6 −2
  8. include/linux/fsnotify_backend.h +3 −7
fs/nfsd/filecache.c+1−1
@@ -792,7 +792,7 @@ nfsd_file_cache_init(void) · 791 unmodified lines
792792 }
793793
794794 nfsd_file_fsnotify_group = fsnotify_alloc_group(&nfsd_file_fsnotify_ops,
795− FSNOTIFY_GROUP_NOFS);
795+ 0);
796796 if (IS_ERR(nfsd_file_fsnotify_group)) {
797797 pr_err("nfsd: unable to create fsnotify group: %ld\n",
798798 PTR_ERR(nfsd_file_fsnotify_group));
fs/notify/dnotify/dnotify.c+1−2
@@ -406,8 +406,7 @@ static int __init dnotify_init(void) · 405 unmodified lines
406406 SLAB_PANIC|SLAB_ACCOUNT);
407407 dnotify_mark_cache = KMEM_CACHE(dnotify_mark, SLAB_PANIC|SLAB_ACCOUNT);
408408
409− dnotify_group = fsnotify_alloc_group(&dnotify_fsnotify_ops,
410− FSNOTIFY_GROUP_NOFS);
409+ dnotify_group = fsnotify_alloc_group(&dnotify_fsnotify_ops, 0);
411410 if (IS_ERR(dnotify_group))
412411 panic("unable to allocate fsnotify group for dnotify\n");
413412 dnotify_sysctl_init();
fs/notify/fanotify/fanotify_user.c+1−1
@@ -1480,7 +1480,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) · 1479 unmodified lines
14801480
14811481 /* fsnotify_alloc_group takes a ref. Dropped in fanotify_release */
14821482 group = fsnotify_alloc_group(&fanotify_fsnotify_ops,
1483− FSNOTIFY_GROUP_USER | FSNOTIFY_GROUP_NOFS);
1483+ FSNOTIFY_GROUP_USER);
14841484 if (IS_ERR(group)) {
14851485 return PTR_ERR(group);
14861486 }
fs/notify/fsnotify.c+12−9
@@ -183,8 +183,10 @@ static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask, · 182 unmodified lines
183183 BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT);
184184
185185 /* Did either inode/sb/mount subscribe for events with parent/name? */
186− marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask);
187− marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask);
186+ marks_mask |= fsnotify_parent_needed_mask(
187+ READ_ONCE(inode->i_fsnotify_mask));
188+ marks_mask |= fsnotify_parent_needed_mask(
189+ READ_ONCE(inode->i_sb->s_fsnotify_mask));
188190 marks_mask |= fsnotify_parent_needed_mask(mnt_mask);
189191
190192 /* Did they subscribe for this event with parent/name info? */
@@ -195,8 +197,8 @@ static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask, · 4 unmodified lines
195197 static inline bool fsnotify_object_watched(struct inode *inode, __u32 mnt_mask,
196198 __u32 mask)
197199 {
198− __u32 marks_mask = inode->i_fsnotify_mask | mnt_mask |
199− inode->i_sb->s_fsnotify_mask;
200+ __u32 marks_mask = READ_ONCE(inode->i_fsnotify_mask) | mnt_mask |
201+ READ_ONCE(inode->i_sb->s_fsnotify_mask);
200202
201203 return mask & marks_mask & ALL_FSNOTIFY_EVENTS;
202204 }
@@ -213,7 +215,8 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, · 10 unmodified lines
213215 int data_type)
214216 {
215217 const struct path *path = fsnotify_data_path(data, data_type);
216− __u32 mnt_mask = path ? real_mount(path->mnt)->mnt_fsnotify_mask : 0;
218+ __u32 mnt_mask = path ?
219+ READ_ONCE(real_mount(path->mnt)->mnt_fsnotify_mask) : 0;
217220 struct inode *inode = d_inode(dentry);
218221 struct dentry *parent;
219222 bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
@@ -557,13 +560,13 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 337 unmodified lines
557560 (!inode2 || !inode2->i_fsnotify_marks))
558561 return 0;
559562
560− marks_mask = sb->s_fsnotify_mask;
563+ marks_mask = READ_ONCE(sb->s_fsnotify_mask);
561564 if (mnt)
562− marks_mask |= mnt->mnt_fsnotify_mask;
565+ marks_mask |= READ_ONCE(mnt->mnt_fsnotify_mask);
563566 if (inode)
564− marks_mask |= inode->i_fsnotify_mask;
567+ marks_mask |= READ_ONCE(inode->i_fsnotify_mask);
565568 if (inode2)
566− marks_mask |= inode2->i_fsnotify_mask;
569+ marks_mask |= READ_ONCE(inode2->i_fsnotify_mask);
567570
568571
569572 /*
fs/notify/group.c+0−11
@@ -115,7 +115,6 @@ static struct fsnotify_group *__fsnotify_alloc_group( · 114 unmodified lines
115115 const struct fsnotify_ops *ops,
116116 int flags, gfp_t gfp)
117117 {
118− static struct lock_class_key nofs_marks_lock;
119118 struct fsnotify_group *group;
120119
121120 group = kzalloc(sizeof(struct fsnotify_group), gfp);
@@ -136,16 +135,6 @@ static struct fsnotify_group *__fsnotify_alloc_group( · 14 unmodified lines
136135
137136 group->ops = ops;
138137 group->flags = flags;
139− /*
140− * For most backends, eviction of inode with a mark is not expected,
141− * because marks hold a refcount on the inode against eviction.
142− *
143− * Use a different lockdep class for groups that support evictable
144− * inode marks, because with evictable marks, mark_mutex is NOT
145− * fs-reclaim safe - the mutex is taken when evicting inodes.
146− */
147− if (flags & FSNOTIFY_GROUP_NOFS)
148− lockdep_set_class(&group->mark_mutex, &nofs_marks_lock);
149138
150139 return group;
151140 }
fs/notify/inotify/inotify_user.c+1−1
@@ -569,7 +569,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, · 568 unmodified lines
569569 /* more bits in old than in new? */
570570 int dropped = (old_mask & ~new_mask);
571571 /* more bits in this fsn_mark than the inode's mask? */
572− int do_inode = (new_mask & ~inode->i_fsnotify_mask);
572+ int do_inode = (new_mask & ~READ_ONCE(inode->i_fsnotify_mask));
573573
574574 /* update the inode with this new fsn_mark */
575575 if (dropped || do_inode)
fs/notify/mark.c+6−2
@@ -128,7 +128,7 @@ __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn) · 127 unmodified lines
128128 if (WARN_ON(!fsnotify_valid_obj_type(conn->type)))
129129 return 0;
130130
131− return *fsnotify_conn_mask_p(conn);
131+ return READ_ONCE(*fsnotify_conn_mask_p(conn));
132132 }
133133
134134 static void fsnotify_get_sb_watched_objects(struct super_block *sb)
@@ -245,7 +245,11 @@ static void *__fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) · 110 unmodified lines
245245 !(mark->flags & FSNOTIFY_MARK_FLAG_NO_IREF))
246246 want_iref = true;
247247 }
248− *fsnotify_conn_mask_p(conn) = new_mask;
248+ /*
249+ * We use WRITE_ONCE() to prevent silly compiler optimizations from
250+ * confusing readers not holding conn->lock with partial updates.
251+ */
252+ WRITE_ONCE(*fsnotify_conn_mask_p(conn), new_mask);
249253
250254 return fsnotify_update_iref(conn, want_iref);
251255 }
include/linux/fsnotify_backend.h+3−7
@@ -217,7 +217,6 @@ struct fsnotify_group { · 216 unmodified lines
217217
218218 #define FSNOTIFY_GROUP_USER 0x01 /* user allocated group */
219219 #define FSNOTIFY_GROUP_DUPS 0x02 /* allow multiple marks per object */
220−#define FSNOTIFY_GROUP_NOFS 0x04 /* group lock is not direct reclaim safe */
221220 int flags;
222221 unsigned int owner_flags; /* stored flags of mark_mutex owner */
223222
@@ -268,22 +267,19 @@ struct fsnotify_group { · 44 unmodified lines
268267 static inline void fsnotify_group_lock(struct fsnotify_group *group)
269268 {
270269 mutex_lock(&group->mark_mutex);
271− if (group->flags & FSNOTIFY_GROUP_NOFS)
272− group->owner_flags = memalloc_nofs_save();
270+ group->owner_flags = memalloc_nofs_save();
273271 }
274272
275273 static inline void fsnotify_group_unlock(struct fsnotify_group *group)
276274 {
277− if (group->flags & FSNOTIFY_GROUP_NOFS)
278− memalloc_nofs_restore(group->owner_flags);
275+ memalloc_nofs_restore(group->owner_flags);
279276 mutex_unlock(&group->mark_mutex);
280277 }
281278
282279 static inline void fsnotify_group_assert_locked(struct fsnotify_group *group)
283280 {
284281 WARN_ON_ONCE(!mutex_is_locked(&group->mark_mutex));
285− if (group->flags & FSNOTIFY_GROUP_NOFS)
286− WARN_ON_ONCE(!(current->flags & PF_MEMALLOC_NOFS));
282+ WARN_ON_ONCE(!(current->flags & PF_MEMALLOC_NOFS));
287283 }
288284
289285 /* When calling fsnotify tell it if the data is a path or inode */