CVE-2026-68082

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
08/08/2026
Last modified:
08/08/2026

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> libceph: fix two unsafe bare decodes in decode_lockers()<br /> <br /> decode_lockers() in cls_lock_client.c contains two bare decode operations<br /> that allow a malicious or compromised OSD to trigger slab-out-of-bounds<br /> reads:<br /> <br /> 1. ceph_decode_32(p) at the num_lockers field has no preceding bounds<br /> check. ceph_start_decoding() accepts struct_len=0 as valid -- the<br /> internal ceph_decode_need(p, end, 0, bad) always passes -- so when an<br /> OSD sends struct_len=0, ceph_start_decoding() returns success with<br /> p == end. The immediately following bare ceph_decode_32(p) then reads<br /> 4 bytes past the validated buffer boundary. The garbage value is<br /> passed directly to kzalloc_objs() as the locker count.<br /> <br /> The sibling function decode_watchers() in osd_client.c already uses<br /> ceph_decode_32_safe() after its own ceph_start_decoding() call.<br /> decode_lockers() was the only site using the bare variant.<br /> <br /> 2. ceph_decode_8(p) after the decode_locker() loop has no preceding<br /> bounds check. If an OSD crafts num_lockers such that the loop<br /> advances p exactly to end, the subsequent bare ceph_decode_8(p) reads<br /> one byte past the validated buffer boundary. The result is passed<br /> directly into *type, which is used as a lock type discriminator by<br /> callers, giving an OSD-controlled one-byte OOB read with direct<br /> influence over the lock type field.<br /> <br /> Fix both by replacing bare operations with their safe variants:<br /> ceph_decode_32(p) -&gt; ceph_decode_32_safe(p, end, *num_lockers,<br /> err_inval)<br /> ceph_decode_8(p) -&gt; ceph_decode_8_safe(p, end, *type,<br /> err_free_lockers)<br /> <br /> The goto targets differ intentionally:<br /> err_inval: is a new label returning -EINVAL directly. It is used for<br /> the pre-allocation failure path where *lockers is not yet allocated<br /> and must not be passed to ceph_free_lockers().<br /> <br /> err_free_lockers: is the existing label. It is used for the<br /> post-allocation failure path where *lockers is allocated and must<br /> be freed.<br /> <br /> ret is set to -EINVAL before ceph_decode_8_safe() so that<br /> err_free_lockers returns the correct error code on bounds violation.<br /> Without this, err_free_lockers would return a stale ret value (0 from<br /> the successful decode_locker() loop), silently swallowing the error.<br /> <br /> -EINVAL is correct for both failure paths. The data received from the<br /> OSD is structurally malformed. -ENOMEM would misrepresent the failure<br /> class to callers and to stable@ backporters triaging error paths.<br /> <br /> Attacker model: a malicious or compromised OSD in a multi-tenant Ceph<br /> deployment can trigger this against any kernel client that issues the<br /> lock.get_info class method (e.g. during RBD exclusive lock acquisition).<br /> <br /> [ idryomov: trim changelog, formatting ]

Impact