CVE-2026-31519
Medium · 5.5CVSS
5.5
EPSS
0.2%
Published
Apr 22, 2026
CISA due date
—
Cloudanix analysis
A local user or workload can trigger a Linux filesystem bug that may make Btrfs folders or subvolumes unusable and disrupt services until the system is repaired or updated.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- Moderate
- Impact
- Denial Of Service
- Component
- OS kernel
- Class
- Denial of service
- Remediation
- Patch
- Effort
- Low
- Patch risk
- Low
What it actually does
This is a local denial-of-service flaw in the Linux kernel Btrfs filesystem. A race condition during Btrfs subvolume creation and orphan cleanup can leave a valid subvolume represented by a negative or broken dentry in the kernel dentry cache. The affected directory entry may appear with unknown permissions and metadata, fail stat operations, resist deletion with ENOENT, block recreation with EEXIST, and in some cases trigger Btrfs filesystem abort behavior. The impact is availability-only: the issue does not directly provide code execution, privilege escalation, or data disclosure, but it can make parts of a Btrfs filesystem unusable until cache state is cleared, the filesystem is repaired, or the system is restarted.
Why it matters to the business
Systems using Btrfs can experience local filesystem disruption, failed file or subvolume operations, service instability, and possible application outages if workloads depend on dynamic subvolume creation, deletion, snapshots, containers, build sandboxes, or user-writable Btrfs areas. Because exploitation requires local authenticated access and there is no known public exploitation or CISA KEV listing, the broad internet-facing risk is low; however, multi-user Linux systems, developer hosts, container platforms, backup/snapshot systems, and storage appliances using Btrfs should treat this as an operational reliability risk.
How an attack unfolds
An attacker with local access to a system using Btrfs triggers a timing-sensitive sequence involving subvolume creation, file creation or writeback activity, unlinking, dentry cache eviction, and subsequent lookup into the affected subvolume. The race can cause Btrfs orphan cleanup to run at the wrong time because the newly created subvolume did not have BTRFS_ROOT_ORPHAN_CLEANUP set during creation. If orphan cleanup encounters missing orphan state and returns ENOENT, the VFS may install a negative dentry for an otherwise valid subvolume. From that point, normal filesystem operations against the subvolume path can fail inconsistently: listing the parent may show a broken entry, stat may fail, deletion may return ENOENT, creating a replacement may return EEXIST, and the filesystem may abort when conflicting operations are attempted. A practical exploit would likely be a local stress/race tool rather than a single deterministic command.
How to fix it
Apply a Linux kernel update that includes the Btrfs fix setting BTRFS_ROOT_ORPHAN_CLEANUP during subvolume creation. No exact fixed kernel versions were provided in the input, so use vendor advisories for the specific distribution or appliance kernel and update to the first patched package available. Where immediate patching is not possible, reduce exposure by limiting local users who can create Btrfs subvolumes, disabling untrusted workloads from using writable Btrfs subvolume operations, avoiding Btrfs for untrusted multi-tenant scratch space, and monitoring for Btrfs orphan cleanup errors. If a system is already affected, dropping dentry cache or rebooting may temporarily clear the broken negative dentry state, but these are mitigations rather than permanent fixes. Any filesystem that has aborted or remounted read-only should be handled according to vendor Btrfs recovery guidance before returning it to production.
How to confirm the fix worked
Confirm whether the running kernel includes the vendor patch for this Btrfs change by checking the installed kernel package changelog, distribution security advisory, or upstream commit backport status. Verify that affected systems are actually using Btrfs with commands such as findmnt -t btrfs or filesystem inventory tooling. After patching, reboot into the updated kernel and confirm with uname -r and package manager metadata that the fixed kernel is active, not merely installed. Operational validation should include creating, deleting, listing, and stat-ing Btrfs subvolumes under representative workload conditions and confirming that no broken dentry entries appear and no kernel logs contain the orphan cleanup failure string. If prior symptoms were observed, validate that the affected subvolume paths can be listed, stat-ed, removed, or recreated normally after remediation and recovery actions.
Typical attack path
- Gain local authenticated access to a Linux system using a Btrfs filesystem.
- Identify a writable location where Btrfs subvolumes can be created and removed, or where a workload already performs these operations.
- Repeatedly create Btrfs subvolumes while generating file writeback, unlink, and close activity inside or around the subvolume.
- Attempt to force or wait for dentry cache eviction while delayed inode references remain active.
- Trigger lookup into the affected subvolume so Btrfs orphan cleanup runs and encounters missing orphan state.
- Cause the kernel to cache a negative dentry for a valid subvolume, producing a broken directory entry.
- Use repeated file, delete, or create operations against the broken path to disrupt applications or potentially force a Btrfs filesystem abort.
How to detect it
To determine whether this was already triggered, examine kernel logs rather than network telemetry, because exploitation is local and filesystem-state based. Review journalctl -k, dmesg, persistent syslog, kern.log, and centralized Linux log collection for Btrfs orphan cleanup failures, Btrfs filesystem aborts, read-only remounts, and repeated ENOENT/EEXIST errors involving subvolume paths. Correlate these events with auditd, shell history, sudo logs, process accounting, EDR telemetry, or container runtime logs showing frequent btrfs subvolume create/delete operations, unlink-heavy workloads, or local stress activity. Look for parent directories containing entries that list as unknown metadata, fail stat, cannot be deleted because they return ENOENT, but cannot be recreated because the name returns EEXIST. Because this issue has no known public exploit maturity and no KEV listing, isolated occurrences may be caused by workload races rather than malicious activity; prioritize cases involving untrusted local users, suspicious automation, or deliberate high-frequency filesystem operations.
- could not do orphan cleanup -2
- btrfs_orphan_cleanup
- BTRFS error
- BTRFS: error
- BTRFS warning
- filesystem forced readonly
- remounting filesystem read-only
What your security team should do
- Inventory Linux systems using Btrfs, prioritizing servers that allow local user access, containerized workloads, developer build jobs, snapshot automation, or frequent subvolume lifecycle operations.
- Patch affected systems to a vendor kernel containing the Btrfs subvolume orphan-cleanup fix and reboot to ensure the patched kernel is running.
- Until patched, restrict untrusted users and workloads from creating or deleting Btrfs subvolumes and reduce use of Btrfs-backed writable shared scratch areas.
- Add monitoring for the kernel log message "could not do orphan cleanup -2" and treat it as a high-confidence indicator of this failure mode or closely related Btrfs corruption state.
- Review systems with prior Btrfs filesystem aborts, unexpected read-only remounts, or unexplained ENOENT/EEXIST conflicts on subvolume paths for possible exposure.
- For critical Btrfs-backed services, ensure current backups and recovery procedures are tested before applying filesystem repair or recovery operations.
The record
In the Linux kernel, the following vulnerability has been resolved: btrfs: set BTRFS_ROOT_ORPHAN_CLEANUP during subvol create We have recently observed a number of subvolumes with broken dentries. ls-ing the parent dir looks like: drwxrwxrwt 1 root root 16 Jan 23 16:49 . drwxr-xr-x 1 root root 24 Jan 23 16:48 .. d????????? ? ? ? ? ? broken_subvol and similarly stat-ing the file fails. In this state, deleting the subvol fails with ENOENT, but attempting to create a new file or subvol over it errors out with EEXIST and even aborts the fs. Which leaves us a bit stuck. dmesg contains a single notable error message reading: "could not do orphan cleanup -2" 2 is ENOENT and the error comes from the failure handling path of btrfs_orphan_cleanup(), with the stack leading back up to btrfs_lookup(). btrfs_lookup btrfs_lookup_dentry btrfs_orphan_cleanup // prints that message and returns -ENOENT After some detailed inspection of the internal state, it became clear that: - there are no orphan items for the subvol - the subvol is otherwise healthy looking, it is not half-deleted or anything, there is no drop progress, etc. - the subvol was created a while ago and does the meaningful first btrfs_orphan_cleanup() call that sets BTRFS_ROOT_ORPHAN_CLEANUP much later. - after btrfs_orphan_cleanup() fails, btrfs_lookup_dentry() returns -ENOENT, which results in a negative dentry for the subvolume via d_splice_alias(NULL, dentry), leading to the observed behavior. The bug can be mitigated by dropping the dentry cache, at which point we can successfully delete the subvolume if we want. i.e., btrfs_lookup() btrfs_lookup_dentry() if (!sb_rdonly(inode->vfs_inode)->vfs_inode) btrfs_orphan_cleanup(sub_root) test_and_set_bit(BTRFS_ROOT_ORPHAN_CLEANUP) btrfs_search_slot() // finds orphan item for inode N ... prints "could not do orphan cleanup -2" if (inode == ERR_PTR(-ENOENT)) inode = NULL; return d_splice_alias(NULL, dentry) // NEGATIVE DENTRY for valid subvolume btrfs_orphan_cleanup() does test_and_set_bit(BTRFS_ROOT_ORPHAN_CLEANUP) on the root when it runs, so it cannot run more than once on a given root, so something else must run concurrently. However, the obvious routes to deleting an orphan when nlinks goes to 0 should not be able to run without first doing a lookup into the subvolume, which should run btrfs_orphan_cleanup() and set the bit. The final important observation is that create_subvol() calls d_instantiate_new() but does not set BTRFS_ROOT_ORPHAN_CLEANUP, so if the dentry cache gets dropped, the next lookup into the subvolume will make a real call into btrfs_orphan_cleanup() for the first time. This opens up the possibility of concurrently deleting the inode/orphan items but most typical evict() paths will be holding a reference on the parent dentry (child dentry holds parent->d_lockref.count via dget in d_alloc(), released in __dentry_kill()) and prevent the parent from being removed from the dentry cache. The one exception is delayed iputs. Ordered extent creation calls igrab() on the inode. If the file is unlinked and closed while those refs are held, iput() in __dentry_kill() decrements i_count but does not trigger eviction (i_count > 0). The child dentry is freed and the subvol dentry's d_lockref.count drops to 0, making it evictable while the inode is still alive. Since there are two races (the race between writeback and unlink and the race between lookup and delayed iputs), and there are too many moving parts, the following three diagrams show the complete picture. (Only the second and third are races) Phase 1: Create Subvol in dentry cache without BTRFS_ROOT_ORPHAN_CLEANUP set btrfs_mksubvol() lookup_one_len() __lookup_slow() d_alloc_parallel() __d_alloc() // d_lockref.count = 1 create_subvol(dentry) // doesn't touch the bit.. d_instantiate_new(dentry, inode) // dentry in cache with d_lockref.c ---truncated---
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|
Related vulnerabilities
- CVE-2026-112405 Pillow is a Python imaging library. CWE-476
- CVE-2026-112392 Pillow is a Python imaging library. CWE-476
- CVE-2026-100348 kin-openapi is a Go project for handling OpenAPI files. CWE-476
- CVE-2026-100349 kin-openapi is a Go project for handling OpenAPI files. CWE-476
- CVE-2026-109280 ImageMagick 7.1.0-20 before 7.1.2-32 contains a use after free vulnerability in the -fx… CWE-476
- CVE-2026-109272 ImageMagick 7.1.1-31 before 7.1.2-32 contains a NULL pointer dereference in the… CWE-476
- CVE-2026-109258 ImageMagick 7.1.0-20 before 7.1.2-32 contains an invalid memory free vulnerability in the… CWE-476
- CVE-2026-107655 A flaw was found in CUPS. CWE-476