ocfs2: validate rl_used against rl_count in refcount block validator

Summary

CVECVE-2026-89493
StatePUBLISHED
AssignerLinux
Source PriorityCVE Program / NVD first with legacy fallback
Published2026-09-11 20:19:31 UTC
Updated2026-09-11 20:19:31 UTC
DescriptionIn the Linux kernel, the following vulnerability has been resolved: ocfs2: validate rl_used against rl_count in refcount block validator ocfs2_find_refcount_rec_in_rl() walks the on-disk refcount record array with: for (; i < le16_to_cpu(rb->rf_records.rl_used); i++) { rec = &rb->rf_records.rl_recs[i]; ... rl_recs[] lives in a single metadata block (4096 bytes on the common configuration), so its real capacity is fixed by ocfs2_refcount_recs_per_rb(sb) (247 records for a 4K block with the 16-byte ocfs2_refcount_rec). rl_used and rl_count are both read directly off disk by ocfs2_validate_refcount_block() 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 rl_used == 0xffff makes the loop above walk far past the end of the block, dereferencing rl_recs[i] for i up to 65534. The resulting index is then handed to the sibling ocfs2_insert_refcount_rec(), whose insert-shift does: if (index < le16_to_cpu(rf_list->rl_used)) memmove(&rf_list->rl_recs[index + 1], &rf_list->rl_recs[index], (le16_to_cpu(rf_list->rl_used) - index) * sizeof(struct ocfs2_refcount_rec)); 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: CAP_SYS_ADMIN mounting a crafted or corrupted ocfs2 image, or a raw write to the block device backing an already-mounted ocfs2 filesystem. ocfs2_validate_refcount_block() already validates the block's ECC, signature, rf_blkno and rf_fs_generation, but never rl_count/rl_used against the block's actual on-disk capacity. This is the same class of gap that ocfs2_validate_extent_block() (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 h_list.l_recs[]: if (le16_to_cpu(eb->h_list.l_count) != ocfs2_extent_recs_per_eb(sb)) { rc = ocfs2_error(...); goto bail; } if (le16_to_cpu(eb->h_list.l_next_free_rec) > le16_to_cpu(eb->h_list.l_count)) { rc = ocfs2_error(...); goto bail; } Add the equivalent pair of checks to ocfs2_validate_refcount_block(): reject a refcount block whose rl_count does not match the fixed per-block capacity returned by ocfs2_refcount_recs_per_rb(), and reject rl_used > rl_count. Both checks are skipped when OCFS2_REFCOUNT_TREE_FL is set, because in that case the same union bytes hold an ocfs2_extent_list (rf_list), not the refcount record list (rf_records) -- that layout is already validated separately by ocfs2_validate_extent_block() when the referenced extent block is read. This mirrors the existing "!(rb->rf_flags & OCFS2_REFCOUNT_TREE_FL)" guard used elsewhere in this file (e.g. ocfs2_get_refcount_rec()) to decide whether rf_records or rf_list is the live member of the union. With this in place, a forged rl_used/rl_count is caught at block validation time (ocfs2_error()), consistent with every other corruption check in this function, instead of driving an out-of-bounds read in ocfs2_find_refcount_rec_in_rl() and a subsequent out-of-bounds memmove() in ocfs2_insert_refcount_rec(). Verified against a crafted image on a v6.19 KASAN (KASAN_GENERIC) build: replaying the same reflink (FICLONE) reliably hit a KASAN report in __ocfs2_increase_refcount()/ocfs2_insert_refcount_rec() before this patch, and triggers no report once ocfs2_validate_refcount_block() rejects the forged rl_used/rl_count.

Vendor Declared Affected Products

SourceVendorProductVersionPlatforms
CNA Linux Linux affected f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 af56e90cb546cb0c47bef059335365283f61d6a4 git Not specified
CNA Linux Linux affected f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 0761d2c9494424469a0d30a9da3496ca010b0b2d git Not specified
CNA Linux Linux affected f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 04ead708e13ddcb9c39319cbe02a18cef99cb823 git Not specified
CNA Linux Linux affected f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 4ca62df6bc0708947b48da3f6a712ecb8e73929c git Not specified
CNA Linux Linux affected 2.6.32 Not specified
CNA Linux Linux unaffected 2.6.32 semver Not specified
CNA Linux Linux unaffected 6.12.109 6.12.* semver Not specified
CNA Linux Linux unaffected 6.18.50 6.18.* semver Not specified
CNA Linux Linux unaffected 7.2.4 7.2.* semver Not specified
CNA Linux Linux unaffected 7.3-rc1 * original_commit_for_fix Not specified

References

ReferenceSourceLinkTags
git.kernel.org/stable/c/af56e90cb546cb0c47bef059335365283f61d6a4 416baaa9-dc9f-4396-8d5f-8c081fb06d67 git.kernel.org
git.kernel.org/stable/c/4ca62df6bc0708947b48da3f6a712ecb8e73929c 416baaa9-dc9f-4396-8d5f-8c081fb06d67 git.kernel.org
git.kernel.org/stable/c/0761d2c9494424469a0d30a9da3496ca010b0b2d 416baaa9-dc9f-4396-8d5f-8c081fb06d67 git.kernel.org
git.kernel.org/stable/c/04ead708e13ddcb9c39319cbe02a18cef99cb823 416baaa9-dc9f-4396-8d5f-8c081fb06d67 git.kernel.org
CVE Program record CVE.ORG www.cve.org canonical
NVD vulnerability detail NVD nvd.nist.gov canonical, analysis

© CVE.report 2026

Use of this information constitutes acceptance for use in an AS IS condition. There are NO warranties, implied or otherwise, with regard to this information or its use. Any use of this information is at the user's risk. It is the responsibility of user to evaluate the accuracy, completeness or usefulness of any information, opinion, advice or other content. EACH USER WILL BE SOLELY RESPONSIBLE FOR ANY consequences of his or her direct or indirect use of this web site. ALL WARRANTIES OF ANY KIND ARE EXPRESSLY DISCLAIMED. This site will NOT BE LIABLE FOR ANY DIRECT, INDIRECT or any other kind of loss.

CVE, CWE, and OVAL are registred trademarks of The MITRE Corporation and the authoritative source of CVE content is MITRE's CVE web site. This site includes MITRE data granted under the following license.

Free CVE JSON API cve.report/api

CVE.report and Source URL Uptime Status status.cve.report