CVE-2026-89493: ocfs2: validate rl_used against rl_count in refcount block validator
In the Linux kernel, the following vulnerability has been resolved:
ocfs2: validate rlused against rlcount in refcount block validator
ocfs2findrefcountrecinrl() walks the on-disk refcount record array with:
for (; i < le16tocpu(rb->rfrecords.rlused); i++) { rec = &rb->rfrecords.rlrecs[i]; ...
rlrecs[] lives in a single metadata block (4096 bytes on the common configuration), so its real capacity is fixed by ocfs2refcountrecsperrb(sb) (247 records for a 4K block with the 16-byte ocfs2refcountrec). rlused and rlcount are both read directly off disk by ocfs2validaterefcountblock() and are never checked against that capacity, nor against each other, before any refcount/reflink/CoW operation walks the array.
A crafted (or corrupted) refcount block with rlused == 0xffff makes the loop above walk far past the end of the block, dereferencing rlrecs[i] for i up to 65534. The resulting index is then handed to the sibling ocfs2insertrefcountrec(), whose insert-shift does:
if (index < le16tocpu(rflist->rlused)) memmove(&rflist->rlrecs[index + 1], &rflist->rlrecs[index], (le16tocpu(rflist->rlused) - index) sizeof(struct ocfs2refcountrec));
i.e. a memmove() of up to (0xffff - index) 16 bytes (~1 MiB) from an offset already past the block. This is reachable from an ordinary reflink (FICLONE) against a crafted/corrupted ocfs2 image: attaching an extent whose cpos sorts past every real record in the leaf forces the lookup to run off the end instead of returning early on a match. The attacker model is local: CAPSYSADMIN mounting a crafted or corrupted ocfs2 image, or a raw write to the block device backing an already-mounted ocfs2 filesystem.
ocfs2validaterefcountblock() already validates the block's ECC, signature, rfblkno and rffsgeneration, but never rlcount/rlused against the block's actual on-disk capacity. This is the same class of gap that ocfs2validateextentblock() (fs/ocfs2/alloc.c) already closes for the sibling extent-list header, which checks both the record capacity and the "used" bound before any code walks hlist.lrecs[]:
if (le16tocpu(eb->hlist.lcount) != ocfs2extentrecspereb(sb)) { rc = ocfs2error(...); goto bail; }
if (le16tocpu(eb->hlist.lnextfreerec) > le16tocpu(eb->hlist.lcount)) { rc = ocfs2error(...); goto bail; }
Add the equivalent pair of checks to ocfs2validaterefcountblock(): reject a refcount block whose rlcount does not match the fixed per-block capacity returned by ocfs2refcountrecsperrb(), and reject rlused > rlcount. Both checks are skipped when OCFS2REFCOUNTTREEFL is set, because in that case the same union bytes hold an ocfs2extentlist (rflist), not the refcount record list (rfrecords) -- that layout is already validated separately by ocfs2validateextentblock() when the referenced extent block is read. This mirrors the existing "!(rb->rfflags & OCFS2REFCOUNTTREEFL)" guard used elsewhere in this file (e.g. ocfs2getrefcountrec()) to decide whether rfrecords or rflist is the live member of the union.
With this in place, a forged rlused/rlcount is caught at block validation time (ocfs2error()), consistent with every other corruption check in this function, instead of driving an out-of-bounds read in ocfs2findrefcountrecinrl() and a subsequent out-of-bounds memmove() in ocfs2insertrefcountrec().
Verified against a crafted image on a v6.19 KASAN (KASANGENERIC) build: replaying the same reflink (FICLONE) reliably hit a KASAN report in ocfs2increaserefcount()/ocfs2insertrefcountrec() before this patch, and triggers no report once ocfs2validaterefcountblock() rejects the forged rlused/rlcount.
Affected Software
Event History
Frequently Asked Questions
Which environments are exposed to this issue?
Linux systems using OCFS2 are exposed when they perform refcount, reflink, or copy-on-write operations that walk an on-disk refcount record array. The issue concerns malformed or corrupted OCFS2 refcount blocks.
What does an attacker need to control to trigger the vulnerable path?
The attacker needs a crafted on-disk refcount block, or an existing refcount block must be corrupted. In particular, a malicious rl_used value can cause the kernel to iterate beyond the metadata block's refcount-record array.
What on-disk values indicate a dangerous refcount block?
A refcount block is dangerous when rl_used or rl_count exceeds the record capacity of its metadata block, or when the two values are inconsistent. On a common 4K-block configuration, the described record-array capacity is 247 records; rl_used set to 0xffff can drive traversal far beyond that boundary.