CVE-2026-90183 in Linux
Summary
by MITRE • 09/17/2026
In the Linux kernel, the following vulnerability has been resolved:
blk-iolatency: clear delay state when freeing policy data
io.latency can throttle a group which has no latency target of its own. When a sibling misses its target, check_scale_change() scales down its peers, and a peer that reaches queue depth one gets blkcg_use_delay() called on it on every further scale-down, even with min_lat_nsec == 0.
iolatency_pd_offline() resets the target through iolatency_set_min_lat_nsec(), which clears the delay only on a nonzero to zero transition, so it never clears such a peer. Freeing the policy data then leaves blkg->use_delay set and blkcg->congestion_count elevated with nothing left that can drop it.
blk_cgroup_congested() then returns true for every task in that cgroup and its descendants for as long as the cgroup lives: page_cache_sync_ra() cuts readahead to a single page, page_cache_async_ra() skips it altogether, and __folio_throttle_swaprate() takes swap_avail_lock and schedules a throttle on anonymous folio allocation.
Clear the delay in iolatency_pd_free(). By then bio-held blkg references have drained, or the queue is frozen for policy deactivation, so check_scale_change() cannot re-arm it. The free callback can also see policy data which was never attached to a blkg, hence the pd->blkg check.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.
Analysis
by VulDB Data Team • 09/17/2026
The Linux kernel block layer latency control subsystem contains a logic error in its resource cleanup path that results in persistent I/O throttling for cgroups after their associated policies are removed. This vulnerability stems from an asymmetry between how delay states are activated and deactivated within the blk-iolatency mechanism. Specifically, when a sibling group misses its latency target, the check_scale_change function scales down peer groups to maintain overall system balance. If a peer reaches a queue depth of one during this process, it triggers blkcg_use_delay(), which marks the block cgroup as requiring delay enforcement. However, the subsequent offline operation that resets targets via iolatency_set_min_lat_nsec only clears the delay state when transitioning from a nonzero latency value to zero. Consequently, if a peer was throttled due to queue depth rather than an explicit high-latency target setting, the condition for clearing the delay is never met during normal policy deactivation.
This oversight leads to a stale state where blkg->use_delay remains set and blkcg->congestion_count stays elevated even after all relevant policy data has been freed. Because no subsequent mechanism exists to drop these counters or reset the flag, the system incorrectly perceives the cgroup as congested indefinitely. This misclassification persists for the entire lifetime of the control group, affecting not only the immediate processes but also any descendant groups within that hierarchy. The impact is severe because it artificially restricts I/O performance without cause, leading to significant degradation in read and write operations across applications relying on those cgroups.
The operational consequences manifest primarily through aggressive throttling mechanisms triggered by blk_cgroup_congested returning true erroneously. For sequential reads, page_cache_sync_ra reduces the readahead window to a single page instead of allowing larger prefetches, drastically lowering throughput for large file accesses. Similarly, page_cache_async_ra skips asynchronous readahead entirely, preventing the kernel from optimizing future I/O patterns based on historical access data. In write scenarios involving swap space, __folio_throttle_swaprate acquires the swap_avail_lock and schedules throttling on anonymous folio allocation, which can cause noticeable latency spikes in memory-intensive workloads that rely on swapping or temporary file storage. These effects compound over time as more tasks attempt to perform I/O within the affected cgroup hierarchy.
From a vulnerability classification perspective, this issue aligns with CWE-401 Missing Release of Resource after Effective Lifetime and CWE-756 Missing Correct Authorization in certain contexts where state management fails during teardown sequences. It also relates to improper resource cleanup patterns often seen in kernel subsystems that manage dynamic policy states without robust finalization hooks. The ATT&CK framework does not directly map this specific kernel bug, but it reflects a class of issues related to system configuration errors and potential denial-of-service conditions arising from internal state corruption rather than external exploitation.
The resolution involves modifying the iolatency_pd_free function to explicitly clear the delay state regardless of whether the transition was zero-to-zero or non-zero-to-zero. This ensures that when policy data is deallocated, all associated throttling flags are reset appropriately. The fix includes a safety check for pd->blkg to handle cases where policy data might not have been fully attached to a block group context during initialization failures or early teardown scenarios. By performing this cleanup at the free callback stage, developers ensure that bio-held references have drained and queues are frozen, preventing race conditions where check_scale_change could re-arm throttling after it has supposedly been disabled. This approach guarantees consistent state management throughout the lifecycle of I/O latency policies within the Linux kernel block layer.