Description
In the Linux kernel, the following vulnerability has been resolved:

KVM: Reject wrapped offset in kvm_reset_dirty_gfn()

kvm_reset_dirty_gfn() guards the gfn range with

if (!memslot || (offset + __fls(mask)) >= memslot->npages)
return;

but offset is u64 and the addition is unchecked. The check can be
silently bypassed by a u64 wrap.

The dirty ring backing those entries is MAP_SHARED at
KVM_DIRTY_LOG_PAGE_OFFSET of the vcpu fd, so the VMM can rewrite the
slot and offset fields of any entry between when the kernel pushes
them and when KVM_RESET_DIRTY_RINGS consumes them. On reset,
kvm_dirty_ring_reset() re-reads the values via READ_ONCE() and feeds
them straight back into this check; only the flags handshake is
treated as the handover, the slot/offset payload is taken on trust.

Crafting two entries

entry[i].offset = 0xffffffffffffffc1
entry[i+1].offset = 0

makes the coalescing loop in kvm_dirty_ring_reset() compute

delta = (s64)(0 - 0xffffffffffffffc1) = 63

which falls in [0, BITS_PER_LONG), so it folds entry[i+1] into the
existing mask by setting bit 63. The trailing kvm_reset_dirty_gfn()
call then sees offset = 0xffffffffffffffc1 and __fls(mask) = 63;
the sum is 0 in u64 and the bounds check passes.

That offset propagates into kvm_arch_mmu_enable_log_dirty_pt_masked()
unchanged. On the legacy MMU path -- kvm_memslots_have_rmaps() ==
true, i.e. shadow paging, any VM that has allocated shadow roots, or
a write-tracked slot -- it reaches gfn_to_rmap(), which indexes
slot->arch.rmap[0][] with a near-U64_MAX gfn. That is an
out-of-bounds load of a kvm_rmap_head, followed by a conditional
clear of PT_WRITABLE_MASK in whatever the loaded pointer points at.
The path is reachable from any process holding /dev/kvm.

Range-check offset on its own first, so the addition cannot wrap.
memslot->npages is bounded well below U64_MAX, so once offset <
npages holds, offset + __fls(mask) (with __fls(mask) < BITS_PER_LONG)
stays in range.
Published: 2026-06-24
Score: 7.0 High
EPSS: < 1% Very Low
KEV: No
Impact: n/a
Action: n/a
AI Analysis

Impact

In the Linux kernel’s KVM subsystem, a 64‑bit addition in the bounds check for dirty‑ring entry processing is unchecked, allowing a crafted offset to wrap around and bypass the guard. The resulting out‑of‑bounds read/write corrupts MMU data structures, which can lead to privilege escalation or kernel instability. The weakness is an integer overflow (CWE‑190).

Affected Systems

All versions of the Linux kernel that expose the /dev/kvm device and implement the dirty ring logic are impacted. The vulnerable code path was fixed in a 2026 kernel update, so any kernel build before that change, across mainstream distributions shipping KVM, remains vulnerable. No specific version numbers are listed in the advisory.

Risk and Exploitability

Based on the description, the likely attack vector is local or containerised access to /dev/kvm, where the attacker must be able to write to the dirty ring entries to manipulate the offset field. The unchecked arithmetic can trigger a wrap‑around that bypasses bounds checks. The CVSS score of 7.0 indicates moderate severity, while the EPSS score of less than 1 % shows a low probability of exploitation in the wild. The vulnerability is not in the CISA KEV catalog, but the potential for privilege escalation warrants urgent attention.

Generated by OpenCVE AI on June 26, 2026 at 05:39 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Apply the kernel patch that introduces the bounds‑check guard against unsigned wrap‑around in kvm_reset_dirty_gfn(), eliminating the integer overflow vulnerability (CWE‑190).
  • If a patch is not immediately available, restrict write access to /dev/kvm to trusted users or disable KVM for untrusted containers or workloads to prevent malicious manipulation that could trigger the overflow (CWE‑190).
  • Enable kernel hardening options such as CONFIG_STRICT_KERNEL_RWX, SELinux or AppArmor policies that limit KVM usage, and enforce strict memory bounds checks to mitigate potential overflows (CWE‑190).

Generated by OpenCVE AI on June 26, 2026 at 05:39 UTC.

Tracking

Sign in to view the affected projects.

Advisories
Source ID Title
Debian DLA Debian DLA DLA-4665-1 linux security update
Debian DLA Debian DLA DLA-4671-1 linux-6.1 security update
History

Fri, 26 Jun 2026 03:00:00 +0000

Type Values Removed Values Added
Weaknesses CWE-125

Fri, 26 Jun 2026 00:15:00 +0000

Type Values Removed Values Added
References
Metrics threat_severity

None

cvssV3_1

{'score': 7.0, 'vector': 'CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H'}

threat_severity

Important


Wed, 24 Jun 2026 18:45:00 +0000

Type Values Removed Values Added
Weaknesses CWE-125
CWE-190

Wed, 24 Jun 2026 17:15:00 +0000

Type Values Removed Values Added
Description In the Linux kernel, the following vulnerability has been resolved: KVM: Reject wrapped offset in kvm_reset_dirty_gfn() kvm_reset_dirty_gfn() guards the gfn range with if (!memslot || (offset + __fls(mask)) >= memslot->npages) return; but offset is u64 and the addition is unchecked. The check can be silently bypassed by a u64 wrap. The dirty ring backing those entries is MAP_SHARED at KVM_DIRTY_LOG_PAGE_OFFSET of the vcpu fd, so the VMM can rewrite the slot and offset fields of any entry between when the kernel pushes them and when KVM_RESET_DIRTY_RINGS consumes them. On reset, kvm_dirty_ring_reset() re-reads the values via READ_ONCE() and feeds them straight back into this check; only the flags handshake is treated as the handover, the slot/offset payload is taken on trust. Crafting two entries entry[i].offset = 0xffffffffffffffc1 entry[i+1].offset = 0 makes the coalescing loop in kvm_dirty_ring_reset() compute delta = (s64)(0 - 0xffffffffffffffc1) = 63 which falls in [0, BITS_PER_LONG), so it folds entry[i+1] into the existing mask by setting bit 63. The trailing kvm_reset_dirty_gfn() call then sees offset = 0xffffffffffffffc1 and __fls(mask) = 63; the sum is 0 in u64 and the bounds check passes. That offset propagates into kvm_arch_mmu_enable_log_dirty_pt_masked() unchanged. On the legacy MMU path -- kvm_memslots_have_rmaps() == true, i.e. shadow paging, any VM that has allocated shadow roots, or a write-tracked slot -- it reaches gfn_to_rmap(), which indexes slot->arch.rmap[0][] with a near-U64_MAX gfn. That is an out-of-bounds load of a kvm_rmap_head, followed by a conditional clear of PT_WRITABLE_MASK in whatever the loaded pointer points at. The path is reachable from any process holding /dev/kvm. Range-check offset on its own first, so the addition cannot wrap. memslot->npages is bounded well below U64_MAX, so once offset < npages holds, offset + __fls(mask) (with __fls(mask) < BITS_PER_LONG) stays in range.
Title KVM: Reject wrapped offset in kvm_reset_dirty_gfn()
First Time appeared Linux
Linux linux Kernel
CPEs cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
Vendors & Products Linux
Linux linux Kernel
References

Subscriptions

Linux Linux Kernel
cve-icon MITRE

Status: PUBLISHED

Assigner: Linux

Published:

Updated: 2026-07-15T00:45:45.448Z

Reserved: 2026-06-09T07:44:35.375Z

Link: CVE-2026-52969

cve-icon Vulnrichment

No data.

cve-icon NVD

No data.

cve-icon Redhat

Severity : Important

Publid Date: 2026-06-24T00:00:00Z

Links: CVE-2026-52969 - Bugzilla

cve-icon OpenCVE Enrichment

Updated: 2026-06-26T05:45:04Z

Weaknesses
  • CWE-190

    Integer Overflow or Wraparound