Public bug reported: [BUG] It's easy to trigger NULL pointer dereference, just by removing a non-existing device id:
# mkfs.btrfs -f -m single -d single /dev/test/scratch1 \ /dev/test/scratch2 # mount /dev/test/scratch1 /mnt/btrfs # btrfs device remove 3 /mnt/btrfs Then we have the following kernel NULL pointer dereference: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 9 PID: 649 Comm: btrfs Not tainted 5.14.0-rc3-custom+ #35 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 RIP: 0010:btrfs_rm_device+0x4de/0x6b0 [btrfs] btrfs_ioctl+0x18bb/0x3190 [btrfs] ? lock_is_held_type+0xa5/0x120 ? find_held_lock.constprop.0+0x2b/0x80 ? do_user_addr_fault+0x201/0x6a0 ? lock_release+0xd2/0x2d0 ? __x64_sys_ioctl+0x83/0xb0 __x64_sys_ioctl+0x83/0xb0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x44/0xae [CAUSE] Commit a27a94c2b0c7 ("btrfs: Make btrfs_find_device_by_devspec return btrfs_device directly") moves the "missing" device path check into btrfs_rm_device(). But btrfs_rm_device() itself can have case where it only receives @devid, with NULL as @device_path. In that case, calling strcmp() on NULL will trigger the NULL pointer dereference. Before that commit, we handle the "missing" case inside btrfs_find_device_by_devspec(), which will not check @device_path at all if @devid is provided, thus no way to trigger the bug. [FIX] Before calling strcmp(), also make sure @device_path is not NULL. ** Affects: linux-azure-5.8 (Ubuntu) Importance: Undecided Status: Invalid ** Affects: linux-hwe-5.8 (Ubuntu) Importance: Undecided Status: Invalid ** Affects: linux-azure-5.8 (Ubuntu Focal) Importance: Medium Assignee: Tim Gardner (timg-tpi) Status: In Progress ** Affects: linux-hwe-5.8 (Ubuntu Focal) Importance: Medium Assignee: Tim Gardner (timg-tpi) Status: In Progress ** Also affects: linux-hwe-5.8 (Ubuntu Focal) Importance: Undecided Status: New ** Changed in: linux-hwe-5.8 (Ubuntu Focal) Status: New => In Progress ** Changed in: linux-hwe-5.8 (Ubuntu Focal) Assignee: (unassigned) => Tim Gardner (timg-tpi) ** Changed in: linux-hwe-5.8 (Ubuntu Focal) Importance: Undecided => Medium ** Changed in: linux-hwe-5.8 (Ubuntu) Status: New => Invalid ** Also affects: linux-azure-5.8 (Ubuntu) Importance: Undecided Status: New ** Changed in: linux-azure-5.8 (Ubuntu Focal) Status: New => In Progress ** Changed in: linux-azure-5.8 (Ubuntu Focal) Importance: Undecided => Medium ** Changed in: linux-azure-5.8 (Ubuntu Focal) Assignee: (unassigned) => Tim Gardner (timg-tpi) ** Changed in: linux-azure-5.8 (Ubuntu) Status: New => Invalid -- You received this bug notification because you are a member of Kernel Packages, which is subscribed to linux-hwe-5.8 in Ubuntu. https://bugs.launchpad.net/bugs/1945987 Title: linux: btrfs: fix NULL pointer dereference when deleting device by invalid id Status in linux-azure-5.8 package in Ubuntu: Invalid Status in linux-hwe-5.8 package in Ubuntu: Invalid Status in linux-azure-5.8 source package in Focal: In Progress Status in linux-hwe-5.8 source package in Focal: In Progress Bug description: [BUG] It's easy to trigger NULL pointer dereference, just by removing a non-existing device id: # mkfs.btrfs -f -m single -d single /dev/test/scratch1 \ /dev/test/scratch2 # mount /dev/test/scratch1 /mnt/btrfs # btrfs device remove 3 /mnt/btrfs Then we have the following kernel NULL pointer dereference: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 9 PID: 649 Comm: btrfs Not tainted 5.14.0-rc3-custom+ #35 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 RIP: 0010:btrfs_rm_device+0x4de/0x6b0 [btrfs] btrfs_ioctl+0x18bb/0x3190 [btrfs] ? lock_is_held_type+0xa5/0x120 ? find_held_lock.constprop.0+0x2b/0x80 ? do_user_addr_fault+0x201/0x6a0 ? lock_release+0xd2/0x2d0 ? __x64_sys_ioctl+0x83/0xb0 __x64_sys_ioctl+0x83/0xb0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x44/0xae [CAUSE] Commit a27a94c2b0c7 ("btrfs: Make btrfs_find_device_by_devspec return btrfs_device directly") moves the "missing" device path check into btrfs_rm_device(). But btrfs_rm_device() itself can have case where it only receives @devid, with NULL as @device_path. In that case, calling strcmp() on NULL will trigger the NULL pointer dereference. Before that commit, we handle the "missing" case inside btrfs_find_device_by_devspec(), which will not check @device_path at all if @devid is provided, thus no way to trigger the bug. [FIX] Before calling strcmp(), also make sure @device_path is not NULL. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/linux-azure-5.8/+bug/1945987/+subscriptions -- Mailing list: https://launchpad.net/~kernel-packages Post to : kernel-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~kernel-packages More help : https://help.launchpad.net/ListHelp