Skip to content

Commit 5e0b17b

Browse files
dhowellstorvalds
authored andcommitted
afs: Fix NULL deref in afs_dynroot_depopulate()
If an error occurs during the construction of an afs superblock, it's possible that an error occurs after a superblock is created, but before we've created the root dentry. If the superblock has a dynamic root (ie. what's normally mounted on /afs), the afs_kill_super() will call afs_dynroot_depopulate() to unpin any created dentries - but this will oops if the root hasn't been created yet. Fix this by skipping that bit of code if there is no root dentry. This leads to an oops looking like: general protection fault, ... KASAN: null-ptr-deref in range [0x0000000000000068-0x000000000000006f] ... RIP: 0010:afs_dynroot_depopulate+0x25f/0x529 fs/afs/dynroot.c:385 ... Call Trace: afs_kill_super+0x13b/0x180 fs/afs/super.c:535 deactivate_locked_super+0x94/0x160 fs/super.c:335 afs_get_tree+0x1124/0x1460 fs/afs/super.c:598 vfs_get_tree+0x89/0x2f0 fs/super.c:1547 do_new_mount fs/namespace.c:2875 [inline] path_mount+0x1387/0x2070 fs/namespace.c:3192 do_mount fs/namespace.c:3205 [inline] __do_sys_mount fs/namespace.c:3413 [inline] __se_sys_mount fs/namespace.c:3390 [inline] __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9 which is oopsing on this line: inode_lock(root->d_inode); presumably because sb->s_root was NULL. Fixes: 0da0b7f ("afs: Display manually added cells in dynamic root mount") Reported-by: [email protected] Signed-off-by: David Howells <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent cd02217 commit 5e0b17b

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

fs/afs/dynroot.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -382,15 +382,17 @@ void afs_dynroot_depopulate(struct super_block *sb)
382382
net->dynroot_sb = NULL;
383383
mutex_unlock(&net->proc_cells_lock);
384384

385-
inode_lock(root->d_inode);
386-
387-
/* Remove all the pins for dirs created for manually added cells */
388-
list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
389-
if (subdir->d_fsdata) {
390-
subdir->d_fsdata = NULL;
391-
dput(subdir);
385+
if (root) {
386+
inode_lock(root->d_inode);
387+
388+
/* Remove all the pins for dirs created for manually added cells */
389+
list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
390+
if (subdir->d_fsdata) {
391+
subdir->d_fsdata = NULL;
392+
dput(subdir);
393+
}
392394
}
393-
}
394395

395-
inode_unlock(root->d_inode);
396+
inode_unlock(root->d_inode);
397+
}
396398
}

0 commit comments

Comments
 (0)