Skip to content

Commit 073c516

Browse files
congwangtorvalds
authored andcommitted
nsfs: mark dentry with DCACHE_RCUACCESS
Andrey reported a use-after-free in __ns_get_path(): spin_lock include/linux/spinlock.h:299 [inline] lockref_get_not_dead+0x19/0x80 lib/lockref.c:179 __ns_get_path+0x197/0x860 fs/nsfs.c:66 open_related_ns+0xda/0x200 fs/nsfs.c:143 sock_ioctl+0x39d/0x440 net/socket.c:1001 vfs_ioctl fs/ioctl.c:45 [inline] do_vfs_ioctl+0x1bf/0x1780 fs/ioctl.c:685 SYSC_ioctl fs/ioctl.c:700 [inline] SyS_ioctl+0x8f/0xc0 fs/ioctl.c:691 We are under rcu read lock protection at that point: rcu_read_lock(); d = atomic_long_read(&ns->stashed); if (!d) goto slow; dentry = (struct dentry *)d; if (!lockref_get_not_dead(&dentry->d_lockref)) goto slow; rcu_read_unlock(); but don't use a proper RCU API on the free path, therefore a parallel __d_free() could free it at the same time. We need to mark the stashed dentry with DCACHE_RCUACCESS so that __d_free() will be called after all readers leave RCU. Fixes: e149ed2 ("take the targets of /proc/*/ns/* symlinks to separate fs") Cc: Alexander Viro <[email protected]> Cc: Andrew Morton <[email protected]> Reported-by: Andrey Konovalov <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 80d136e commit 073c516

File tree

1 file changed

+1
-0
lines changed

1 file changed

+1
-0
lines changed

fs/nsfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static void *__ns_get_path(struct path *path, struct ns_common *ns)
9191
return ERR_PTR(-ENOMEM);
9292
}
9393
d_instantiate(dentry, inode);
94+
dentry->d_flags |= DCACHE_RCUACCESS;
9495
dentry->d_fsdata = (void *)ns->ops;
9596
d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry);
9697
if (d) {

0 commit comments

Comments
 (0)