Cloudanix VulnDB

CVE-2026-89655

Critical · 9.8

CVSS

9.8

EPSS

0.7%

Published

Sep 11, 2026

CISA due date

—

Cloudanix analysis

Monitor only SSVC: Track

A race condition in Linux storage code can let attackers crash systems or run malicious code by sending storage messages at exactly the wrong moment.

Exploitation
Local Privilege
Attacker needs
Local User
Complexity
Moderate
Impact
Full Compromise
Component
OS kernel
Class
Use After Free
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

Use-after-free during list iteration in ceph cap flushing logic: __kick_flushing_caps drops i_ceph_lock, allowing handle_cap_flush_ack to detach and free cf entries; the loop then dereferences the freed cf->i_list.next pointer.

Why it matters to the business

Linux systems using Ceph may experience kernel crashes or arbitrary code execution from network-triggered races, leading to service outages and potential full host compromise in storage clusters.

How an attack unfolds

An attacker interacts with a Ceph MDS to trigger rapid FLUSH/FLUSH_ACK exchanges while a kernel thread is iterating the cap flush list, freeing an entry under the attacker-controlled timing window and causing the original thread to access freed memory on list advance.

How to fix it

Apply the upstream fix that replaces list_for_each_entry with a manual while loop saving the next pointer under lock before any unlock; rebuild and deploy the patched kernel on all Ceph clients.

How to confirm the fix worked

Confirm the patch is present by inspecting __kick_flushing_caps for the manual while-loop pattern with saved next pointer; run targeted stress tests exercising concurrent cap flushes and acks; verify no UAF reports in kernel logs under load.

Typical attack path

  1. Establish Ceph client connection to MDS
  2. Trigger cap flush operations that populate i_cap_flush_list
  3. Send or induce quick FLUSH_ACK responses while lock is dropped
  4. Force the victim thread to advance the now-stale list entry
  5. Dereference freed memory to achieve UAF primitive

How to detect it

Search kernel logs and dmesg for ceph-related oops, use-after-free warnings, or list corruption panics occurring shortly after MDS cap flush activity; correlate with Ceph client connection and ack traffic in network captures.

  • BUG: KASAN: use-after-free in __kick_flushing_caps
  • list_next_entry.*ceph.*cap
  • ceph_free_cap_flush.*called under lock contention

What your security team should do

  • Immediately upgrade all Ceph client kernels to a version containing the fix
  • Prioritize Ceph storage clusters and any systems mounting CephFS
  • Enable kernel hardening features such as KASAN in test environments to catch similar issues
  • Monitor for kernel oops or panic events related to ceph cap lists

The record

In the Linux kernel, the following vulnerability has been resolved: ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock list_for_each_entry() iterates ci->i_cap_flush_list but drops i_ceph_lock to send cap messages. During the unlock window, handle_cap_flush_ack() can acquire i_ceph_lock, detach cf entries with tid <= flush_tid from the list, release i_ceph_lock, and free them via ceph_free_cap_flush() outside any lock. When the original thread reacquires i_ceph_lock and the for-loop macro advances via cf = list_next_entry(cf, i_list), it dereferences cf->i_list.next on freed memory. The race timeline: __kick_flushing_caps() handle_cap_flush_ack() ----------------------- ----------------------- holds i_ceph_lock <--- iterates to cf (tid=10) prepares FLUSH message drops i_ceph_lock <--- __send_cap() ── FLUSH(tid=10) MDS sends FLUSH_ACK(tid=10) ---> acquires i_ceph_lock cf->tid(10) <= flush_tid(10), detaches cf from i_cap_flush_list drops i_ceph_lock ceph_free_cap_flush(cf) <- frees it! acquires i_ceph_lock <--- for-loop advances: cf = list_next_entry(cf, i_list) -- UAF on freed cf->i_list.next The cf was just sent by __kick_flushing_caps itself via __send_cap(). The MDS may respond with FLUSH_ACK quickly enough that handle_cap_flush_ack() frees cf before __kick_flushing_caps can finish the iteration. Fix by converting to a manual while loop: save the next pointer under i_ceph_lock before dropping it, then use the saved pointer after reacquiring, so the potentially-freed cf is never accessed again.

Affected packages

Ecosystem Package Introduced Fixed