Direct naar de inhoud
Kritieke cyberalerts voor jouw sector & systemen — direct in je inbox. Aanmelden →
CVE's Videos Dagbriefing

← Terug naar CVE-database

CVE-2026-52969

HIGH · 7.8 CVSS Gepubliceerd: CWE-129

Beschrijving NL

In de Linux kernel is de volgende kwetsbaarheid verholpen:

KVM: Verwerpen gewikkelde offset in kvm_reset_dirty_gfn()

kvm_reset_dirty_gfn () bewaakt het gfn-bereik met

if (!memslot || (offset + __fls(masker)) >= memslot- > npagina's)
return;

maar offset is u64 en de toevoeging is niet aangevinkt. De controle kan worden
geruisloos omzeild door een u64 wrap. De vuile ring achter die vermeldingen is MAP_SHARED OP
KVM_DIRTY_LOG_PAGE_OFFSET van de vcpu fd, zodat de VMM de
sleuf- en offsetvelden van elke invoer tussen wanneer de kernel duwt
ze en wanneer KVM_RESET_DIRTY_RINGS ze verbruikt. Bij het resetten,
kvm_dirty_ring_reset() leest de waarden opnieuw via READ_ONCE() en feeds
ze direct terug in deze cheque; alleen de vlaggen handdruk is
behandeld als de overdracht, wordt de slot/offset payload in vertrouwen genomen. Twee inzendingen maken

ingang[i].offset = 0xffffffffffffffc1
invoer[i+1].offset = 0

maakt de coalescentielus in kvm_dirty_ring_reset() compute

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

die in [0, BITS_PER_LONG) valt, dus het vouwt ingang[i+1] in de
bestaand masker door bit 63 in te stellen. De achterliggende kvm_reset_dirty_gfn()
call ziet dan offset = 0xffffffffffffc1 en __fls(masker) = 63;
de som is 0 in u64 en de grenscontrole passeert. Die offset verspreidt zich naar kvm_arch_mmu_enable_log_dirty_pt_masked()
ongewijzigd. Op het oude MMU-pad -- kvm_memslots_have_rmaps() ==
true, d.w.z. schaduwpaginering, elke VM die schaduwwortels heeft toegewezen, of
een schrijf-gevolgd slot -- het bereikt gfn_to_rmap(), die indexeert
slot- >arch.rmap[0][] met een near-U64_MAX gfn. Dat is een
out-of-bounds belasting van een kvm_rmap_head, gevolgd door een voorwaardelijke
vrij van PT_WRITABLE_MASK in waar de geladen aanwijzer ook naar wijst. Het pad is bereikbaar vanuit elk proces dat /dev/kvm bevat. Bereik-controle offset op zijn eigen eerste, zodat de toevoeging kan niet wikkelen. memslot->npages is begrensd ver onder U64_MAX, dus een keer offset <
npages hold, offset + __fls(masker) (met __fls(masker) < BITS_PER_LONG)
binnen bereik blijft.

Origineel (Engels) tonen

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.

Vendors

Linux

Affected products

Linux Kernel

References