ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock
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 pote
- Products
- Kernel
- Affected versions
- Not specified
- Fixed versions
- 5.10.270, 5.15.221, 6.1.188, 6.12.109, 6.18.50, 6.6.157, 7.2.4
- CVEs
- CVE-2026-89655
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 2 Nov 2026, 18:53 UTC · Revision 1
Source evidence
ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock
core-osv · Original sourcePublished 11 Sept 2026, 19:45 UTC
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 pote
osv:CVE-2026-89655
Kernel
Fixed versions: 5.10.270, 5.15.221, 6.1.188, 6.6.157, 6.12.109, 6.18.50, 7.2.4
Complete source record
{
"id": "81a9d8e9445b658054ae9ca9cc818a6f3f865d6a82cd7d2c88eb8c575bd41417",
"url": "https://osv.dev/vulnerability/CVE-2026-89655",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock",
"summary": "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 pote",
"evidence": "osv:CVE-2026-89655",
"products": [
{
"name": {
"value": "Kernel",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "5.10.270",
"evidence": "/affected/1/ranges"
},
{
"value": "5.15.221",
"evidence": "/affected/1/ranges"
},
{
"value": "6.1.188",
"evidence": "/affected/1/ranges"
},
{
"value": "6.6.157",
"evidence": "/affected/1/ranges"
},
{
"value": "6.12.109",
"evidence": "/affected/1/ranges"
},
{
"value": "6.18.50",
"evidence": "/affected/1/ranges"
},
{
"value": "7.2.4",
"evidence": "/affected/1/ranges"
}
],
"affected_versions": []
}
],
"severity": "critical",
"structured": {
"id": "CVE-2026-89655",
"aliases": [
"CVE-2026-89655"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
}
],
"affected": [
{
"ranges": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "e4500b5e35c213e0f97be7cb69328c0877203a79"
},
{
"fixed": "091137821e1fc88f37e15201abf055c9494ddc61"
},
{
"fixed": "01542430081014d80fc9e70e92d6647432ddb7fc"
},
{
"fixed": "23eb34a53a53cb1a6dab1eeee830633207ac158d"
},
{
"fixed": "19f16f04c2b014a7dd214dc1e42557d8530b16f3"
},
{
"fixed": "2701431aa3cc8b23efe6890182e7b04f5e76fab5"
},
{
"fixed": "fe46746087b5b9c5bb2d022df6c7819218494ced"
},
{
"fixed": "2dba24dcd5050be4b7b119e6f0b01f62203b5d26"
},
{
"fixed": "7af4c4f01305b0935adf6d4301b1ec407025485d"
}
]
}
],
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-89655.json"
}
},
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "4.8.0"
},
{
"fixed": "5.10.270"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "5.11.0"
},
{
"fixed": "5.15.221"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "5.16.0"
},
{
"fixed": "6.1.188"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.2.0"
},
{
"fixed": "6.6.157"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.7.0"
},
{
"fixed": "6.12.109"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.13.0"
},
{
"fixed": "6.18.50"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.19.0"
},
{
"fixed": "7.2.4"
}
]
}
],
"package": {
"name": "Kernel",
"ecosystem": "Linux"
},
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-89655.json"
}
}
],
"modified": "2026-10-28T02:30:22.448701184Z",
"provider": "osv",
"references": [
"https://git.kernel.org/stable/c/01542430081014d80fc9e70e92d6647432ddb7fc",
"https://git.kernel.org/stable/c/091137821e1fc88f37e15201abf055c9494ddc61",
"https://git.kernel.org/stable/c/19f16f04c2b014a7dd214dc1e42557d8530b16f3",
"https://git.kernel.org/stable/c/23eb34a53a53cb1a6dab1eeee830633207ac158d",
"https://git.kernel.org/stable/c/2701431aa3cc8b23efe6890182e7b04f5e76fab5",
"https://git.kernel.org/stable/c/2dba24dcd5050be4b7b119e6f0b01f62203b5d26",
"https://git.kernel.org/stable/c/7af4c4f01305b0935adf6d4301b1ec407025485d",
"https://git.kernel.org/stable/c/fe46746087b5b9c5bb2d022df6c7819218494ced",
"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/89xxx/CVE-2026-89655.json",
"https://nvd.nist.gov/vuln/detail/CVE-2026-89655",
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
],
"provider_metadata": {
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/89xxx/CVE-2026-89655.json"
}
},
"related_cves": [
{
"value": "CVE-2026-89655",
"evidence": "/id"
}
],
"security_relevant": true,
"severity_evidence": "/severity/0/score"
},
"source_id": "core-osv",
"document_id": 488820,
"published_at": "2026-09-11T19:45:44.841+00:00"
}