---
id: CVE-2026-89493
title: 'ocfs2: validate rl_used against rl_count in refcount block validator'
summary: "In the Linux kernel, the following vulnerability has been resolved:\n\nocfs2: validate rl_used against rl_count in refcount block validator\n\nocfs2_find_refcount_rec_in_rl() walks the on-disk refcount record array\nwith:\n\n\tfor (; i < le16_to…"
severity: high
cvss: 8.8
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H'
cvssSource: cna
cwe:
  - CWE-787
vendor: Linux
product: Linux
affected:
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    f882e9e32d017a6569b2996c63ba3864717788e6
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    5593b63028cb43a6cda75a65ce1db95f00ea6857
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    c8b02f4ee91e757b3fff556c7168b24b7ae55132
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    97584e93fc49a2d59252ac60467e9279f11b1b5b
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    af56e90cb546cb0c47bef059335365283f61d6a4
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    0761d2c9494424469a0d30a9da3496ca010b0b2d
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    04ead708e13ddcb9c39319cbe02a18cef99cb823
  - >-
    Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 <
    4ca62df6bc0708947b48da3f6a712ecb8e73929c
  - Linux 2.6.32
published: '2026-09-11'
updated: '2026-10-19'
sourceUpdated: '2026-10-19T08:47:44.950Z'
source: CVEORG
sourceUrl: 'https://www.cve.org/CVERecord?id=CVE-2026-89493'
references:
  - url: 'https://git.kernel.org/stable/c/f882e9e32d017a6569b2996c63ba3864717788e6'
  - url: 'https://git.kernel.org/stable/c/5593b63028cb43a6cda75a65ce1db95f00ea6857'
  - url: 'https://git.kernel.org/stable/c/c8b02f4ee91e757b3fff556c7168b24b7ae55132'
  - url: 'https://git.kernel.org/stable/c/97584e93fc49a2d59252ac60467e9279f11b1b5b'
  - url: 'https://git.kernel.org/stable/c/af56e90cb546cb0c47bef059335365283f61d6a4'
  - url: 'https://git.kernel.org/stable/c/0761d2c9494424469a0d30a9da3496ca010b0b2d'
  - url: 'https://git.kernel.org/stable/c/04ead708e13ddcb9c39319cbe02a18cef99cb823'
  - url: 'https://git.kernel.org/stable/c/4ca62df6bc0708947b48da3f6a712ecb8e73929c'
  - url: >-
      https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-89493.json
  - url: 'https://access.redhat.com/security/cve/CVE-2026-89493'
  - url: 'https://bugzilla.redhat.com/show_bug.cgi?id=2532390'
  - url: 'https://www.cve.org/CVERecord?id=CVE-2026-89493'
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-89493'
  - url: >-
      https://git.kernel.org/pub/scm/linux/security/vulns.git/plain/cve/published/2026/CVE-2026-89493.mbox
tags:
  - cve.org
  - csaf
  - vex
  - red-hat
  - score-dispute
epss: 0.0065
epssPercentile: 0.50969
scores:
  cna: 8.8
  vendor: 5.5
ingestedAt: '2026-09-14T15:23:07.452Z'
---

## Overview

In 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.

## Affected

- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < f882e9e32d017a6569b2996c63ba3864717788e6`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < 5593b63028cb43a6cda75a65ce1db95f00ea6857`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < c8b02f4ee91e757b3fff556c7168b24b7ae55132`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < 97584e93fc49a2d59252ac60467e9279f11b1b5b`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < af56e90cb546cb0c47bef059335365283f61d6a4`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < 0761d2c9494424469a0d30a9da3496ca010b0b2d`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < 04ead708e13ddcb9c39319cbe02a18cef99cb823`
- `Linux >= f2c870e3b12e38da6d9b5b17c4c8ae56a0ed68e4 < 4ca62df6bc0708947b48da3f6a712ecb8e73929c`
- `Linux 2.6.32`

## Remediation

Refer to the linked advisories for vendor-supplied fixes and affected version ranges.

## Vendor advisories

- **Red Hat VEX** · Moderate · updated 2026-09-18 · [vex](https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-89493.json)
