CVE-2023-54271 in Linux
Summary
by MITRE • 12/30/2025
In the Linux kernel, the following vulnerability has been resolved:
blk-cgroup: Fix NULL deref caused by blkg_policy_data being installed before init
blk-iocost sometimes causes the following crash:
BUG: kernel NULL pointer dereference, address: 00000000000000e0 ... RIP: 0010:_raw_spin_lock+0x17/0x30 Code: be 01 02 00 00 e8 79 38 39 ff 31 d2 89 d0 5d c3 0f 1f 00 0f 1f 44 00 00 55 48 89 e5 65 ff 05 48 d0 34 7e b9 01 00 00 00 31 c0 <f0> 0f b1 0f 75 02 5d c3 89 c6 e8 ea 04 00 00 5d c3 0f 1f 84 00 00 RSP: 0018:ffffc900023b3d40 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 00000000000000e0 RCX: 0000000000000001 RDX: ffffc900023b3d20 RSI: ffffc900023b3cf0 RDI: 00000000000000e0 RBP: ffffc900023b3d40 R08: ffffc900023b3c10 R09: 0000000000000003 R10: 0000000000000064 R11: 000000000000000a R12: ffff888102337000 R13: fffffffffffffff2 R14: ffff88810af408c8 R15: ffff8881070c3600 FS: 00007faaaf364fc0(0000) GS:ffff88842fdc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000e0 CR3: 00000001097b1000 CR4: 0000000000350ea0 Call Trace: <TASK> ioc_weight_write+0x13d/0x410 cgroup_file_write+0x7a/0x130 kernfs_fop_write_iter+0xf5/0x170 vfs_write+0x298/0x370 ksys_write+0x5f/0xb0 __x64_sys_write+0x1b/0x20 do_syscall_64+0x3d/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0
This happens because iocg->ioc is NULL. The field is initialized by ioc_pd_init() and never cleared. The NULL deref is caused by blkcg_activate_policy() installing blkg_policy_data before initializing it.
blkcg_activate_policy() was doing the following:
1. Allocate pd's for all existing blkg's and install them in blkg->pd[].
2. Initialize all pd's. 3. Online all pd's.
blkcg_activate_policy() only grabs the queue_lock and may release and re-acquire the lock as allocation may need to sleep. ioc_weight_write() grabs blkcg->lock and iterates all its blkg's. The two can race and if ioc_weight_write() runs during #1 or between #1 and #2, it can encounter a pd which is not initialized yet, leading to crash.
The crash can be reproduced with the following script:
#!/bin/bash
echo +io > /sys/fs/cgroup/cgroup.subtree_control systemd-run --unit touch-sda --scope dd if=/dev/sda of=/dev/null bs=1M count=1 iflag=direct echo 100 > /sys/fs/cgroup/system.slice/io.weight bash -c "echo '8:0 enable=1' > /sys/fs/cgroup/io.cost.qos" & sleep .2 echo 100 > /sys/fs/cgroup/system.slice/io.weight
with the following patch applied:
> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c > index fc49be622e05..38d671d5e10c 100644 > --- a/block/blk-cgroup.c > +++ b/block/blk-cgroup.c > @@ -1553,6 +1553,12 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol) > pd->online = false; > } > > + if (system_state == SYSTEM_RUNNING) {
> + spin_unlock_irq(&q->queue_lock); > + ssleep(1); > + spin_lock_irq(&q->queue_lock); > + } > + > /* all allocated, init in the same order */ > if (pol->pd_init_fn) > list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
I don't see a reason why all pd's should be allocated, initialized and onlined together. The only ordering requirement is that parent blkgs to be initialized and onlined before children, which is guaranteed from the walking order. Let's fix the bug by allocating, initializing and onlining pd for each blkg and holding blkcg->lock over initialization and onlining. This ensures that an installed blkg is always fully initialized and onlined removing the the race window.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.
Analysis
by VulDB Data Team • 06/20/2026
The vulnerability described in CVE-2023-54271 represents a critical null pointer dereference flaw within the Linux kernel's block cgroup implementation, specifically affecting the io cost control subsystem. This issue manifests as a kernel panic during system operation when the ioc_weight_write function attempts to access a null pointer at address 0x00000000000000e0, leading to a complete system crash. The root cause lies in the improper sequencing of operations within the blkcg_activate_policy function where policy data structures are installed before they are properly initialized, creating a race condition that can be exploited to trigger the crash.
The technical flaw occurs due to a race condition between two distinct kernel subsystems operating on the same data structures. The blkcg_activate_policy function performs three sequential operations: first allocating policy data structures for all existing block group nodes and installing them, then initializing these structures, and finally bringing them online. However, the function only holds the queue lock during this process and may release and reacquire it during allocation operations that can sleep. Meanwhile, the ioc_weight_write function holds the blkcg->lock and iterates through all block group nodes, creating a window where the two operations can overlap and cause a null pointer dereference when accessing partially initialized policy data structures.
This vulnerability directly maps to CWE-476, which describes a null pointer dereference condition, and aligns with ATT&CK technique T1499.001 for resource hijacking and system instability. The race condition is particularly dangerous because it can be reliably reproduced through a specific sequence of system operations involving cgroup configuration and block I/O operations. The crash occurs when iocg->ioc field is accessed but remains NULL, as it is only initialized by the ioc_pd_init() function and never cleared, creating an inconsistent state in the kernel's block I/O subsystem.
The operational impact of this vulnerability is severe, as it can cause complete system crashes and potential data loss when triggered during normal system operation. Attackers can exploit this vulnerability by carefully orchestrating cgroup operations and block I/O activities to force the race condition, making it particularly concerning for systems running production workloads that rely heavily on block I/O operations and cgroup management. The fix implemented addresses this by restructuring the blkcg_activate_policy function to hold the blkcg->lock throughout the entire initialization and onlining process for each individual block group, ensuring that no partially initialized policy data structures can be accessed by concurrent operations.
The mitigation strategy focuses on maintaining proper ordering and synchronization during the policy data structure initialization process. The patch modifies the blkcg_activate_policy function to ensure that each block group's policy data is fully allocated, initialized, and brought online before proceeding to the next block group, effectively eliminating the race condition. This approach ensures that all installed policy data structures are always in a consistent state, preventing access to null pointers and maintaining system stability. The solution also includes a temporary delay mechanism when the system is running to further reduce the probability of race conditions, though the primary fix ensures that the locking mechanism properly protects the entire initialization sequence, making the system resilient against concurrent access patterns that could previously trigger the crash.