Skip to content

Commit 62ab2cc

Browse files
adam900710kdave
authored andcommitted
btrfs: sysfs: fix NULL pointer dereference at btrfs_sysfs_del_qgroups()
[BUG] Unmounting a btrfs filesystem with quota disabled will cause the following NULL pointer dereference: BTRFS info (device dm-5): has skinny extents BUG: kernel NULL pointer dereference, address: 0000000000000018 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page CPU: 7 PID: 637 Comm: umount Not tainted 5.8.0-rc7-next-20200731-custom #76 RIP: 0010:kobject_del+0x6/0x20 Call Trace: btrfs_sysfs_del_qgroups+0xac/0xf0 [btrfs] btrfs_free_qgroup_config+0x63/0x70 [btrfs] close_ctree+0x1f5/0x323 [btrfs] btrfs_put_super+0x15/0x17 [btrfs] generic_shutdown_super+0x72/0x110 kill_anon_super+0x18/0x30 btrfs_kill_super+0x17/0x30 [btrfs] deactivate_locked_super+0x3b/0xa0 deactivate_super+0x40/0x50 cleanup_mnt+0x135/0x190 __cleanup_mnt+0x12/0x20 task_work_run+0x64/0xb0 exit_to_user_mode_prepare+0x18a/0x190 syscall_exit_to_user_mode+0x4f/0x270 do_syscall_64+0x45/0x50 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ---[ end trace 37b7adca5c1d5c5d ]--- [CAUSE] Commit 079ad2f ("kobject: Avoid premature parent object freeing in kobject_cleanup()") changed kobject_del() that it no longer accepts NULL pointer. Before that commit, kobject_del() and kobject_put() all accept NULL pointers and just ignore such NULL pointers. But that mentioned commit needs to access the parent node, killing the old NULL pointer behavior. Unfortunately btrfs is relying on that hidden feature thus we will trigger such NULL pointer dereference. [FIX] Instead of just saving several lines, do proper fs_info->qgroups_kobj check before calling kobject_del() and kobject_put(). Reviewed-by: Nikolay Borisov <[email protected]> Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent c15c2ec commit 62ab2cc

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

fs/btrfs/sysfs.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,9 +1565,11 @@ void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info)
15651565
rbtree_postorder_for_each_entry_safe(qgroup, next,
15661566
&fs_info->qgroup_tree, node)
15671567
btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
1568-
kobject_del(fs_info->qgroups_kobj);
1569-
kobject_put(fs_info->qgroups_kobj);
1570-
fs_info->qgroups_kobj = NULL;
1568+
if (fs_info->qgroups_kobj) {
1569+
kobject_del(fs_info->qgroups_kobj);
1570+
kobject_put(fs_info->qgroups_kobj);
1571+
fs_info->qgroups_kobj = NULL;
1572+
}
15711573
}
15721574

15731575
/* Called when qgroups get initialized, thus there is no need for locking */

0 commit comments

Comments
 (0)