Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2026-80527

Gravedad CVSS v3.1:
ALTA
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
26/08/2026
Última modificación:
27/08/2026

Descripción

*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> ceph: fix hanging __ceph_get_caps() with stale mds_wanted<br /> <br /> A reader can hang forever in __ceph_get_caps() when the client no<br /> longer holds `FILE_RD`, but local cap state still says that the<br /> capability is already wanted (via `mds_wanted`).<br /> <br /> One way to trigger this is through MDS cap revocation. If another<br /> client performs a conflicting operation, the MDS can revoke `FILE_RD`<br /> from the reader; the next read then has to reacquire `FILE_RD`. If<br /> the cap update that should request `FILE_RD` never reaches the MDS<br /> after `cap-&gt;mds_wanted` was raised, the reader is left holding only<br /> non-file caps while local `mds_wanted` still includes the file read<br /> caps.<br /> <br /> In that state, try_get_cap_refs() sees `need mds_wanted was` raised, no further request is sent and the<br /> waiter can sleep indefinitely until unrelated cap traffic happens to<br /> wake it up.<br /> <br /> The ordering issue is that `cap-&gt;mds_wanted` is updated in<br /> __prep_cap() before the `CEPH_MSG_CLIENT_CAPS message` is actually<br /> queued for send. That makes one field serve two different meanings at<br /> once: what this client wants, and what the client believes the MDS<br /> already knows it wants.<br /> <br /> A proper fix would be to split those states and track whether a cap<br /> update is actually in flight or has been observed by the MDS.<br /> However, simply moving the `cap-&gt;mds_wanted assignment` later would<br /> not be sufficient: queueing the message in the messenger does not<br /> guarantee that the MDS processed that specific wanted set, and<br /> reconnect or message loss can still invalidate that assumption.<br /> Fixing that properly would require a larger rework of the cap state<br /> machine.<br /> <br /> To allow simpler backports to stable kernels, this patch implements a<br /> simpler workaround:<br /> <br /> - stop waiting forever in __ceph_get_caps(); after a bounded wait,<br /> fall back to the renew path<br /> <br /> - make ceph_renew_caps() issue a synchronous `OPEN` request whenever<br /> the inode still does not actually hold the wanted caps, instead of<br /> only calling ceph_check_caps()<br /> <br /> The extra issued-vs-wanted check in ceph_renew_caps() is necessary<br /> because the previous test only checked whether the inode still had any<br /> real caps at all. That is not enough after revocation: the client can<br /> still hold something like `pLs` and yet be missing `FILE_RD`<br /> completely. In that case, falling back to ceph_check_caps() is not<br /> sufficient, because it still trusts `cap-&gt;mds_wanted` and may resend<br /> nothing. By requiring `(issued &amp; wanted) == wanted` before taking the<br /> asynchronous path, the code only uses ceph_check_caps() when the<br /> `wanted caps` are already actually issued. Otherwise, it sends the<br /> synchronous `OPEN` renew.<br /> <br /> This preserves the existing asynchronous fast path when the wanted<br /> caps are already issued, avoids changing cap-state semantics, and<br /> fixes the hang by guaranteeing that a stalled waiter eventually<br /> retries through a path that does not rely on the stale `mds_wanted`<br /> state.<br /> <br /> [ idryomov: move CEPH_GET_CAPS_WAIT_TIMEOUT from libceph.h to<br /> mds_client.h, formatting ]