CVE-2023-52896
Severity CVSS v4.0:
Pending analysis
Type:
CWE-476
NULL Pointer Dereference
Publication date:
21/08/2024
Last modified:
11/09/2024
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: fix race between quota rescan and disable leading to NULL pointer deref<br />
<br />
If we have one task trying to start the quota rescan worker while another<br />
one is trying to disable quotas, we can end up hitting a race that results<br />
in the quota rescan worker doing a NULL pointer dereference. The steps for<br />
this are the following:<br />
<br />
1) Quotas are enabled;<br />
<br />
2) Task A calls the quota rescan ioctl and enters btrfs_qgroup_rescan().<br />
It calls qgroup_rescan_init() which returns 0 (success) and then joins a<br />
transaction and commits it;<br />
<br />
3) Task B calls the quota disable ioctl and enters btrfs_quota_disable().<br />
It clears the bit BTRFS_FS_QUOTA_ENABLED from fs_info->flags and calls<br />
btrfs_qgroup_wait_for_completion(), which returns immediately since the<br />
rescan worker is not yet running.<br />
Then it starts a transaction and locks fs_info->qgroup_ioctl_lock;<br />
<br />
4) Task A queues the rescan worker, by calling btrfs_queue_work();<br />
<br />
5) The rescan worker starts, and calls rescan_should_stop() at the start<br />
of its while loop, which results in 0 iterations of the loop, since<br />
the flag BTRFS_FS_QUOTA_ENABLED was cleared from fs_info->flags by<br />
task B at step 3);<br />
<br />
6) Task B sets fs_info->quota_root to NULL;<br />
<br />
7) The rescan worker tries to start a transaction and uses<br />
fs_info->quota_root as the root argument for btrfs_start_transaction().<br />
This results in a NULL pointer dereference down the call chain of<br />
btrfs_start_transaction(). The stack trace is something like the one<br />
reported in Link tag below:<br />
<br />
general protection fault, probably for non-canonical address 0xdffffc0000000041: 0000 [#1] PREEMPT SMP KASAN<br />
KASAN: null-ptr-deref in range [0x0000000000000208-0x000000000000020f]<br />
CPU: 1 PID: 34 Comm: kworker/u4:2 Not tainted 6.1.0-syzkaller-13872-gb6bb9676f216 #0<br />
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022<br />
Workqueue: btrfs-qgroup-rescan btrfs_work_helper<br />
RIP: 0010:start_transaction+0x48/0x10f0 fs/btrfs/transaction.c:564<br />
Code: 48 89 fb 48 (...)<br />
RSP: 0018:ffffc90000ab7ab0 EFLAGS: 00010206<br />
RAX: 0000000000000041 RBX: 0000000000000208 RCX: ffff88801779ba80<br />
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000<br />
RBP: dffffc0000000000 R08: 0000000000000001 R09: fffff52000156f5d<br />
R10: fffff52000156f5d R11: 1ffff92000156f5c R12: 0000000000000000<br />
R13: 0000000000000001 R14: 0000000000000001 R15: 0000000000000003<br />
FS: 0000000000000000(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000<br />
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br />
CR2: 00007f2bea75b718 CR3: 000000001d0cc000 CR4: 00000000003506e0<br />
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000<br />
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400<br />
Call Trace:<br />
<br />
btrfs_qgroup_rescan_worker+0x3bb/0x6a0 fs/btrfs/qgroup.c:3402<br />
btrfs_work_helper+0x312/0x850 fs/btrfs/async-thread.c:280<br />
process_one_work+0x877/0xdb0 kernel/workqueue.c:2289<br />
worker_thread+0xb14/0x1330 kernel/workqueue.c:2436<br />
kthread+0x266/0x300 kernel/kthread.c:376<br />
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308<br />
<br />
Modules linked in:<br />
<br />
So fix this by having the rescan worker function not attempt to start a<br />
transaction if it didn&#39;t do any rescan work.
Impact
Base Score 3.x
4.70
Severity 3.x
MEDIUM
Vulnerable products and versions
CPE | From | Up to |
---|---|---|
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.4.178 (including) | 5.4.230 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.10.99 (including) | 5.10.165 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.15.22 (including) | 5.15.90 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.16.8 (excluding) | 5.17 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.17 (including) | 6.1.8 (excluding) |
cpe:2.3:o:linux:linux_kernel:6.2:rc1:*:*:*:*:*:* | ||
cpe:2.3:o:linux:linux_kernel:6.2:rc2:*:*:*:*:*:* | ||
cpe:2.3:o:linux:linux_kernel:6.2:rc3:*:*:*:*:*:* | ||
cpe:2.3:o:linux:linux_kernel:6.2:rc4:*:*:*:*:*:* |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/1004fc90f0d79a4b7d9e3d432729914f472f9ad1
- https://git.kernel.org/stable/c/3bd43374857103ba3cac751d6d4afa8d83b5d92a
- https://git.kernel.org/stable/c/64287cd456a22373053998c1fccf14b651e9cbbd
- https://git.kernel.org/stable/c/89ac597e3e807b91e2ebd6a7c36fec7b97290233
- https://git.kernel.org/stable/c/b7adbf9ada3513d2092362c8eac5cddc5b651f5c