data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2026-89647 in the interactive tracker

CVE-2026-89647

ceph: do not repeat ceph_trim_dentries() if no progress possible

7.5 EPSS 0.6% AV:N

Published 2026-09-11 (37 days ago) by the Linux kernel CNA. Subsystem fs/ceph. Debian urgency: not yet assigned.

What to do, per Debian release

Debian's own status for CVE-2026-89647 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

ReleaseStatus VersionWhat this means
Debian 12bookwormvulnerable6.1.190-1No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication.
Debian 13trixiefixedDSA-6528-1 · 2026-09-29 · text6.12.111-1Update the kernel and reboot. DSA-6528-1 shipped the fix on 2026-09-29, in 6.12.111-1. A running kernel keeps the old code until the machine restarts.
Debian 14forkyfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian 12bookworm · linux-6.12fixedDLA-4817-1 · 2026-10-04 · text6.12.111-1~deb12u1Update the kernel and reboot. DLA-4817-1 shipped the fix on 2026-10-04, in 6.12.111-1~deb12u1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

ceph_cap_reclaim_work() re-queues itself for as long as ceph_trim_dentries() returns -EAGAIN, which happens whenever a lease walk exhausts its `nr_to_scan` budget. This creates a busy loop that consumes CPU without making any progress when there is nothing to reclaim: with no cap pressure (`count==0`) and every scanned lease still valid, each pass runs the full scan budget down to zero and returns `-EAGAIN`, only to be queued again immediately. The dir-lease walk made this worse. When `expire_dir_lease` is `false` (i.e. we have no intention of reclaiming dir leases), __dir_lease_check() returned `TOUCH` for every valid lease. `TOUCH` moves the dentry to the tail of the list and resets `di->time` via __dentry_dir_lease_touch(), so a walk over N valid leases pointlessly rewrote the list, refreshed the timestamps (preventing them from ever aging out) and always drained `nr_to_scan`, guaranteeing the `-EAGAIN` requeue. Fix this in three steps: - Return `KEEP` instead of `TOUCH` when `expire_dir_lease` is `false`. If we are not going to reclaim the lease, leave it in place instead of churning the list and resetting its timestamp; the walk then terminates naturally (or via `STOP` at the first fresh lease). - Only return `-EAGAIN` from the first (dentry-lease) walk when something was actually freed. A full batch that frees nothing means retrying the same list immediately is futile; fall through to the dir-lease walk instead. - After both walks, bail out with success (0) when nothing was freed and there is no cap pressure (`count==0`). There is no reason to keep retrying when we are not over the cap limit and made no progress. Under real cap pressure (`count>0`) the reclaim path is unchanged and still retries via `-EAGAIN`. Without this patch, I saw 500 ceph_trim_dentries() calls per second on our web servers. This is very visible in `/proc/lock_stat` (5 minute capture): class name con-bounces contentions waittime-min waittime-max waittime-total waittime-avg acq-bounces acquisitions holdtime-min holdtime-max holdtime-total holdtime-avg &mdsc->dentry_list_lock: 126180 128218 0.04 8063.44 15986965.20 124.69 1573354 5296812 0.04 8291.28 74164526.48 14.00 ----------------------- &mdsc->dentry_list_lock 111736 [<000000007b11e319>] __ceph_dentry_dir_lease_touch+0x7c/0xa8 &mdsc->dentry_list_lock 2631 [<0000000050597999>] __dentry_leases_walk+0x64/0x2c8 &mdsc->dentry_list_lock 3878 [<00000000c0022f62>] __ceph_dentry_lease_touch+0x5c/0xa8 &mdsc->dentry_list_lock 9973 [<000000002f27cb6f>] __dentry_lease_unlist+0x50/0xa0 ----------------------- &mdsc->dentry_list_lock 123621 [<0000000050597999>] __dentry_leases_walk+0x64/0x2c8 &mdsc->dentry_list_lock 1822 [<000000007b11e319>] __ceph_dentry_dir_lease_touch+0x7c/0xa8 &mdsc->dentry_list_lock 2720 [<000000002f27cb6f>] __dentry_lease_unlist+0x50/0xa0 &mdsc->dentry_list_lock 55 [<00000000c0022f62>] __ceph_dentry_lease_touch+0x5c/0xa8 With this patch: class name con-bounces contentions waittime-min waittime-max waittime-total waittime-avg acq-bounces acquisitions holdtime-min holdtime-max holdtime-total holdtime-avg &mdsc->dentry_list_lock: 1203 1215 0.16 408.88 33082.88 27.23 4320501 7357389 0.04 500.64 1961578.00 0.27 ----------------------- &mdsc->dentry_list_lock 1029 [<000000003c9aea8a>] __ceph_dentry_dir_lease_touch+0x7c/0xa8 &mdsc->dentry_list_lock 1 ---truncated---

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/ceph/dir.c

What this is
CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH)MAINTAINERS section matched on fs/ceph/ · ceph-devel@vger.kernel.org · Supported
Kernel module
ceph

Check it on the machine

grep -w CONFIG_CEPH_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 ceph

Prints 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, sid, bookworm · linux-6.12m
m
a loadable module on every flavour - check lsmod, can be blacklisted
Build switch
CONFIG_CEPH_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.5 high
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsource recompute it
Attack vector
network (AV:N)source
EPSS
0.62%, higher than 48.7% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
not yet assignedsource
Subsystem
fs/ceph

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
5.16.12.1095a541eb401ac
5.16.18.5037d6edb2f03b
5.17.2.43d122b2feb1d
5.17.3e7d7aa7b7301

Debian advisories

AdvisoryDateShipped toDebian
DLA-4817-12026-10-04bookworm 6.12.111-1~deb12u1tracker
DSA-6528-12026-09-29trixie 6.12.111-1tracker

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:NAttack vector, network
fs/ceph registers ceph_export_ops, so remote nfsd/ksmbd readdir and lookup on an exported CephFS mount populate dentry and dir-lease lists and drive ceph_trim_dentries() via the cap-reclaim workqueue; a compromised MDS on the existing client TCP session can also keep those leases valid.
AC:LAttack complexity, low
Default caps_max leaves count==0, so expire_dir_lease is false and valid dir leases are TOUCHed until nr_to_scan hits zero; ceph_cap_reclaim_work() then immediately requeues on -EAGAIN. An attacker who walks or creates many dentries, or a peer that grants many still-valid leases, triggers this deterministically with no race.
PR:NPrivileges required, none
In the network-export scenario the attacker needs no local account or capability on the victim host; guest or anonymous NFS/SMB exports of CephFS, and a remote MDS peer on an already-connected kernel client, are reasonable high-severity deployments matching other Ceph client CVEs.
UI:NUser interaction, none
After CephFS is mounted and optionally exported, delayed_work periodically queues reclaim and the attacker’s own readdir/lookup or MDS lease traffic is enough; no separate victim mount, open, or confirmation is required at exploit time.
S:UScope, unchanged
The busy loop, CPU burn, and dentry_list_lock contention stay inside the host kernel CephFS client and do not cross a VM, IOMMU, or sandbox boundary to another security authority.
C:NConfidentiality impact, none
The defect only rescans and TOUCHes still-valid dentry leases; it does not perform an out-of-bounds read, use-after-free, or any other kernel-memory disclosure.
I:NIntegrity impact, none
The walk only reshuffles lease-list order and refreshes dentry timestamps; there is no memory corruption, arbitrary write, or control-flow hijack primitive.
A:HAvailability impact, high
ceph_cap_reclaim_work() immediately requeues itself on -EAGAIN, forming an unbounded busy loop on the max_active=1 ceph-cap workqueue (observed ~500 iterations/s) that starves cap-release work, burns CPU, and contends dentry_list_lock enough to stall Ceph directory operations.