Look up another CVE · open CVE-2026-89767 in the interactive tracker
CVE-2026-89767
ovl: fix double end_creating() on the casefold-mismatch path
Published 2026-09-11 (37 days ago) by the Linux kernel CNA. Subsystem fs/overlayfs. Debian urgency: unimportant.
What to do, per Debian release
Debian's own status for CVE-2026-89767 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source
| Release | Status | Version | What this means |
|---|---|---|---|
| Debian 12bookworm | not affected | 6.1.190-1 | Nothing to do. bookworm never shipped the vulnerable code. |
| Debian 13trixie | not affected | 6.12.113-1 | Nothing to do. trixie never shipped the vulnerable code. |
| Debian 14forky | fixed | 7.2.6-1 | Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts. |
| Debian unstablesid | fixed | 7.2.6-1 | Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts. |
The vulnerability
What the bug is
ovl_create_real() releases the new dentry twice when the casefold consistency check fails. The S_IFDIR branch calls end_creating() and sets err, then falls through to the common out: label which calls end_creating() on the same dentry again: case S_IFDIR: newdentry = ovl_do_mkdir(ofs, dir, newdentry, attr->mode); err = PTR_ERR_OR_ZERO(newdentry); if (!err && ofs->casefold != ovl_dentry_casefolded(newdentry)) { pr_warn_ratelimited(...); end_creating(newdentry); /* first */ err = -EINVAL; } break; ... if (err) goto out; ... out: if (err) { end_creating(newdentry); /* second, same dentry */ return ERR_PTR(err); } end_creating() is end_dirop(), which does inode_unlock() on the parent and dput() on the dentry, so the parent directory's i_rwsem is unlocked twice and the dentry is put twice. The second unlock releases a lock that is not held, which is what wedges every later creation under that parent, and the second dput() drops a reference that was never taken. The branch was added by commit dfc7da402ccc ("ovl: Check for casefold consistency when creating new dentries") as a bare dput(), which already released the reference twice; commit fe497f0759e0 ("VFS: change vfs_mkdir() to unlock on failure.") converted both sites to end_creating(), adding the double unlock. This is reachable by an unprivileged user. The casefold consistency of the layers is validated at mount time in ovl_parse_layer(), and again on every lookup in ovl_lookup_single(), but ofs->workdir is the internal "work" subdirectory created inside the user-supplied workdir, and that subdirectory is not re-checked. Marking it casefolded after the mount therefore makes every ovl_create_temp() inherit the wrong state - and that path reaches ovl_create_real() through ovl_start_creating_temp(), which uses start_creating() with a generated name and so never runs the lookup-time check. unshare -Urm mount -t tmpfs -o casefold=utf8-12.1.0 tmpfs mnt mkdir -p mnt/lower/d mnt/upper mnt/work mnt/merged mount -t overlay ovl -o lowerdir=mnt/lower,\ upperdir=mnt/upper,workdir=mnt/work mnt/merged chattr +F mnt/work/work mkdir mnt/merged/d/sub # directory copy-up overlayfs: wrong inherited casefold (work/#5) and the next copy-up blocks forever on the parent's i_rwsem: mkdir D start_creating+0x65/0xb0 ovl_start_creating_temp+0xb0/0xe0 [overlay] ovl_create_temp+0xa3/0x1d0 [overlay] ovl_copy_up_one+0x1f1c/0x21c0 [overlay] ovl_copy_up_flags+0xf5/0x140 [overlay] ovl_create_object+0xb7/0x220 [overlay] ovl_mkdir+0x23/0x40 [overlay] Drop the end_creating() from the branch and let out: own the cleanup, which is what every other error path in this function already does.
Where it lives
The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.
fs/overlayfs/dir.c
- What this is
- OVERLAY FILESYSTEMMAINTAINERS section matched on fs/overlayfs/ · linux-unionfs@vger.kernel.org · Supported
- Kernel module
- overlay
Check it on the machine
grep -w CONFIG_OVERLAY_FS /boot/config-$(uname -r)Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.
lsmod | grep -w overlayPrints a line if that module is loaded right now, and nothing if it is not. One that is not loaded can still be loaded later by anything that needs it.
Show whether Debian builds this, per release
Debian builds this as a loadable module. Every release below compiles it as a module on every flavour, so whether the code is in the running kernel depends on whether that module is loaded.
- bookworm, trixie, forky, sidm
- m
- a loadable module on every flavour - check lsmod, can be blacklisted
- Build switch
- CONFIG_OVERLAY_FS
From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages
Signals
- Published
- 2026-09-11 (37 days ago)source
- CVSS
- 7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it - Attack vector
- local (AV:L)source
- EPSS
- 0.17%, higher than 6.3% of all CVEssource
- CISA KEV
- not listedthe KEV catalogue
- Debian urgency
- unimportantsource
- Subsystem
- fs/overlayfs
Upstream fixes
The versions the CNA records as introducing and fixing this, and the commit for each. source
| Introduced | Fixed in | Commit |
|---|---|---|
| 6.18 | 6.18.51 | 2fa220bc0f84 |
| 6.18 | 7.2.4 | b1aa8ab78a8e |
| 6.18 | 7.3 | 077ab8985ee2 |
Why the CNA scored it this way
Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source
- AV:LAttack vector, local
- The bug is in overlayfs ovl_create_real() on the S_IFDIR casefold-mismatch path, reached from local mkdir/creat copy-up (ovl_mkdir → ovl_create_object → ovl_copy_up_one → ovl_create_temp). An unprivileged user can mount overlay on tmpfs in a user+mount namespace; this is not a network packet path.
- AC:LAttack complexity, low
- The attacker fully controls the overlay mount, the post-mount chattr +F on the internal work/ workdir, and the mkdir that forces directory copy-up. The mismatch is deterministic with no race or victim state beyond the attacker's control.
- PR:LPrivileges required, low
- Overlayfs sets FS_USERNS_MOUNT, so a normal local user can unshare a user and mount namespace, mount overlay, and reach ovl_create_real without init-namespace root. The commit's unshare -Urm reproducer matches this unprivileged path.
- UI:NUser interaction, none
- The attacker mounts the overlay, marks the internal workdir casefolded, and issues mkdir themselves. No separate victim action is required.
- S:UScope, unchanged
- Double end_creating() corrupts kernel VFS locking and dentry references on the local host. This stays within the kernel's security authority and is not a VM escape, IOMMU bypass, or other cross-boundary impact.
- C:HConfidentiality impact, high
- end_creating() is end_dirop(), which inode_unlock()s the parent and dput()s the dentry. The extra dput can free or underflow a still-used dentry, and the extra unlock corrupts i_rwsem so concurrent VFS operations can race, enabling kernel memory disclosure.
- I:HIntegrity impact, high
- Double dput plus double inode_unlock of the parent i_rwsem break directory serialization and dentry lifetime. That enables use-after-free and unsynchronized create/lookup on the workdir, a high-integrity kernel memory-corruption primitive.
- A:HAvailability impact, high
- The extra unlock leaves the workdir i_rwsem corrupt so later copy-up/create sleeps uninterruptibly in D state, and the extra dput/UAF can oops or panic the kernel. Either outcome is high availability impact.