Skip to content

[rlc-8/4.18.0-553.139.1.el8_10] Multiple patches tested (2 commits)#1404

Open
ciq-kernel-automation[bot] wants to merge 2 commits into
rlc-8/4.18.0-553.139.1.el8_10from
{shreeya_januscape}_rlc-8/4.18.0-553.139.1.el8_10
Open

[rlc-8/4.18.0-553.139.1.el8_10] Multiple patches tested (2 commits)#1404
ciq-kernel-automation[bot] wants to merge 2 commits into
rlc-8/4.18.0-553.139.1.el8_10from
{shreeya_januscape}_rlc-8/4.18.0-553.139.1.el8_10

Conversation

@ciq-kernel-automation

@ciq-kernel-automation ciq-kernel-automation Bot commented Jul 6, 2026

Copy link
Copy Markdown

Summary

This PR has been automatically created after successful completion of all CI stages.

Commit Message(s)

KVM: x86: Fix shadow paging use-after-free due to unexpected GFN

cve CVE-2026-46113
commit-author Sean Christopherson <seanjc@google.com>
commit -
commit-source-sha 0cb2af2ea66ad95873455d8a1d0f6f4e13fef645
commit-source https://lore.kernel.org/all/20260626112634.1778506-1-pbonzini@redhat.com/
upstream-diff |
	This is a HAND-PORT, not a cherry-pick.  Upstream commit
	0cb2af2ea66ad fixes kvm_mmu_get_child_sp() by adding a
	spte_to_child_sp(*sptep)->gfn == gfn check to its -EEXIST reuse
	guard.  That function (and spte_to_child_sp/kvm_mmu_child_role,
	the whole get_child_sp/get_shadow_page split) does NOT exist on
	this 4.18-based tree, which predates the ~6.2 KVM MMU refactor and
	still uses kvm_mmu_get_page() + link_shadow_page().
KVM: x86: Fix shadow paging use-after-free due to unexpected role

cve CVE-2026-53359
commit-author Paolo Bonzini <pbonzini@redhat.com>
commit -
commit-source-sha 81ccda30b4e83d8f5cc4fd50503c44e3a33abfeb
commit-source https://lore.kernel.org/all/20260626112634.1778506-1-pbonzini@redhat.com/
upstream-diff |
	This is a HAND-PORT, not a cherry-pick.  Upstream commit
	81ccda30b4e8 fixes kvm_mmu_get_child_sp() by adding
	spte_to_child_sp(*sptep)->role.word == role.word to its -EEXIST
	reuse guard, on top of the unexpected-GFN check.  That function does
	not exist on this 4.18-based tree (see the prerequisite "unexpected
	GFN" commit for the full rationale); the equivalent guard lives in
	the shared helper kvm_mmu_child_sp_matches() applied at the three
	fault-path reuse sites.  This commit adds the role.word comparison
	to that helper, using kvm_mmu_child_role() to derive the expected
	role exactly as kvm_mmu_get_page() does.  Functionally equivalent to
	upstream.

Reproducing and testing Januscape

Prerequisites

  1. A bare-metal host running RLC 8 without the two fixes (GFN + role).
  2. A guest VM (also RLC 8, or any kernel, the guest kernel is not what matters).
  3. Nested virtualization enabled on the host (kvm_intel nested=1), and the guest CPU set to host-passthrough so it can run the PoC's nested VMX/EPT workload.

Steps (inside the guest)

  1. Copy poc.c and Makefile into the guest.
  2. Build the module:
    make
  3. Load it (unload the guest's kvm_intel first for a clean slate):
    sudo rmmod kvm_intel
    sudo insmod poc.ko
  4. The PoC pins CPU and races the host's page-fault handler. A single insmod does not always win the race - it may crash on the first run, or take several.
  5. If it doesn't crash, unload and retry:
    sudo rmmod poc
    sudo insmod poc.ko
  6. Repeat. On an unpatched host you should see a crash within ~10 runs (a fresh insmod re-primes the race window each time).

Expected result

The host panics with a KVM shadow-MMU rmap corruption, with a signature like:

gfn mismatch under direct page <A> (expected <B>, got <C>)
pte_list_remove: <ptr> 0->BUG          # el9 / 5.14: pte_list_remove, mmu.c:940
kernel BUG at arch/x86/kvm/mmu/mmu.c:940!
RIP: pte_list_remove+... [kvm]
Call Trace: kvm_mmu_page_fault → mmu_set_spte → ... [kvm]
Comm: CPU N/KVM

Verifying the fix

Install the patched kernel on the host, boot into it, and repeat the same PoC runs from the guest. With the fix applied the host survives all runs (no pte_list_remove)

Test Results

✅ Build Stage

Architecture Build Time Total Time
x86_64 19m 31s 20m 30s
aarch64 11m 9s 11m 46s

✅ Boot Verification

✅ Kernel Selftests

Architecture Passed Failed Compared Against Status
x86_64 122 34 rlc-8/4.18.0-553.139.1.el8_10 ⚠️ No baseline available
aarch64 73 31 rlc-8/4.18.0-553.139.1.el8_10 ⚠️ No baseline available

✅ LTP Results

Architecture Passed Failed Compared Against Status
x86_64 1403 83 rlc-8/4.18.0-553.139.1.el8_10 ⚠️ No baseline available
aarch64 1381 83 rlc-8/4.18.0-553.139.1.el8_10 ⚠️ No baseline available

🤖 This PR was automatically generated by GitHub Actions
Run ID: 28800827773

cve CVE-2026-46113
commit-author Sean Christopherson <seanjc@google.com>
commit -
commit-source-sha 0cb2af2ea66ad95873455d8a1d0f6f4e13fef645
commit-source https://lore.kernel.org/all/20260626112634.1778506-1-pbonzini@redhat.com/
upstream-diff |
	This is a HAND-PORT, not a cherry-pick.  Upstream commit
	0cb2af2 fixes kvm_mmu_get_child_sp() by adding a
	spte_to_child_sp(*sptep)->gfn == gfn check to its -EEXIST reuse
	guard.  That function (and spte_to_child_sp/kvm_mmu_child_role,
	the whole get_child_sp/get_shadow_page split) does NOT exist on
	this 4.18-based tree, which predates the ~6.2 KVM MMU refactor and
	still uses kvm_mmu_get_page() + link_shadow_page().

	On this tree the interior-SPTE reuse happens in the fault-path
	walkers __direct_map() and FNAME(fetch): after drop_large_spte(),
	a present non-large SPTE is reused as-is (skipping the
	kvm_mmu_get_page() alloc path that would validate gfn), with no
	re-check that the referenced child shadow page still maps the
	expected gfn.  The equivalent guard is therefore applied at each of
	the three reuse sites via a shared helper kvm_mmu_child_sp_matches();
	on mismatch the stale child SPTE is zapped (mmu_page_zap_pte + remote
	flush) so the correct child is (re)allocated.  kvm_mmu_child_role()
	factors out kvm_mmu_get_page()'s role derivation so the guard and the
	allocator cannot drift.  Functionally equivalent to upstream.

Commit 0cb2af2 ("KVM: x86: Fix shadow paging use-after-free due to
unexpected GFN") fixes a shadow paging mismatch between the stored and
computed GFNs.  The bug can be triggered by changing a PDE mapping from
outside the guest and then deleting a memslot: rmap_remove() misses
entries whose leaf SPTE gfn does not match the gfn of the struct
kvm_mmu_page.  The freed shadow page's rmap entry survives, and later
walks of that gfn (dirty logging, MMU notifier invalidation, ...)
dereference an sptep in the freed page, causing the use-after-free.

Fixes: 2032a93 ("KVM: MMU: Don't allocate gfns page for direct mmu pages")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Shreeya Patel <spatel@ciq.com>
(cherry picked from commit 77a7e0c53f10a5e3eb48ae52a8ea7844904f5fff)
cve CVE-2026-53359
commit-author Paolo Bonzini <pbonzini@redhat.com>
commit -
commit-source-sha 81ccda3
commit-source https://lore.kernel.org/all/20260626112634.1778506-1-pbonzini@redhat.com/
upstream-diff |
	This is a HAND-PORT, not a cherry-pick.  Upstream commit
	81ccda3 fixes kvm_mmu_get_child_sp() by adding
	spte_to_child_sp(*sptep)->role.word == role.word to its -EEXIST
	reuse guard, on top of the unexpected-GFN check.  That function does
	not exist on this 4.18-based tree (see the prerequisite "unexpected
	GFN" commit for the full rationale); the equivalent guard lives in
	the shared helper kvm_mmu_child_sp_matches() applied at the three
	fault-path reuse sites.  This commit adds the role.word comparison
	to that helper, using kvm_mmu_child_role() to derive the expected
	role exactly as kvm_mmu_get_page() does.  Functionally equivalent to
	upstream.

Commit 0cb2af2 ("KVM: x86: Fix shadow paging use-after-free due to
unexpected GFN") fixed a shadow paging mismatch between stored and
computed GFNs.  A similar hole remains if the modified PDE points to a
non-leaf page: the gfn can be made to match, but the role does not.  The
original large 2MB page creates a kvm_mmu_page with direct=1, while the
new 4KB mapping needs one with direct=0; because the reuse path did not
compare the role, the direct=1 page was reused.  Installing a leaf SPTE
then records an rmap entry under the walk's gfn, but when that child is
zapped its parent has direct=1 and kvm_mmu_page_get_gfn() computes the
gfn as sp->gfn + index instead of using sp->gfns[], so the recorded
entry is not removed.  When the memslot is dropped the shadow page is
freed but the rmap entry survives, and later walks dereference an sptep
in the freed page, causing the use-after-free.

Fixes: 2032a93 ("KVM: MMU: Don't allocate gfns page for direct mmu pages")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Shreeya Patel <spatel@ciq.com>
(cherry picked from commit 1b5de8ad73a7a312c68374860bab5bbce44075a9)
@ciq-kernel-automation ciq-kernel-automation Bot added the created-by-kernelci Tag PRs that were automatically created when a user branch was pushed to the repo (kernelCI) label Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/28814796100

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Validation checks completed successfully View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/28814796100

@PlaidCat PlaidCat requested a review from a team July 6, 2026 20:42

@bmastbergen bmastbergen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥌

@bmastbergen bmastbergen requested a review from a team July 6, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

created-by-kernelci Tag PRs that were automatically created when a user branch was pushed to the repo (kernelCI)

Development

Successfully merging this pull request may close these issues.

2 participants