From: Sean Christopherson <seanjc@google.com>
To: punixcorn <ohyunwoods663@gmail.com>
Cc: pbonzini@redhat.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [BUG] KVM: NULL pointer dereference in kvm_tdp_mmu_map under memory pressure
Date: Wed, 8 Apr 2026 07:18:27 -0700 [thread overview]
Message-ID: <adZjswAhbcQmekxZ@google.com> (raw)
In-Reply-To: <20260408102914.106838-1-ohyunwoods663@gmail.com>
On Wed, Apr 08, 2026, punixcorn wrote:
> Under host memory pressure, a NULL pointer dereference occurs in
> kvm_tdp_mmu_map() at offset 0x24. The exact root cause is unclear --
> it may be an unhandled NULL return from tdp_mmu_alloc_sp(), or a
> violated invariant elsewhere in the map path.
It's pretty much guaranteed to be the latter.
tdp_mmu_alloc_sp() can't fail, as KVM ensures vcpu->arch.mmu_page_header_cache
holds enough pre-allocated entries to service the page fault. Even if that
invariant fails and KVM exhausts the cache, it should still be impossible for
kvm_mmu_memory_cache_alloc() to return NULL because it will either use a fallback
allocation (after WARNing) and succeed, or BUG_ON() and prevent hitting the NULL
pointer deref.
void *kvm_mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
{
void *p;
if (WARN_ON(!mc->nobjs))
p = mmu_memory_cache_alloc_obj(mc, GFP_ATOMIC | __GFP_ACCOUNT);
else
p = mc->objects[--mc->nobjs];
BUG_ON(!p);
return p;
}
And even if _that_ didn't suffice, tdp_mmu_alloc_sp() itself deferences the
return sp, so the NULL pointer deref would happen earlier.
static struct kvm_mmu_page *tdp_mmu_alloc_sp(struct kvm_vcpu *vcpu)
{
struct kvm_mmu_page *sp;
sp = kvm_mmu_memory_cache_alloc(&vcpu->arch.mmu_page_header_cache);
sp->spt = kvm_mmu_memory_cache_alloc(&vcpu->arch.mmu_shadow_page_cache);
return sp;
}
>
> Crash log:
>
> BUG: kernel NULL pointer dereference, address: 0000000000000024
> #PF: supervisor read access in kernel mode
> Oops: 0000 [#1] SMP NOPTI
> CPU: 2 PID: 1110212 Comm: MainLoopThread Tainted: G U OE 6.19.10-arch1-1
> Hardware name: Default Default/NLXB, BIOS BQ141 06/27/2024
> RIP: 0010:kvm_tdp_mmu_map+0x471/0x880 [kvm]
> Code: 00 00 00 80 48 2b 35 76 72 5c c8 48 c7 44 24 20 00 00 00 00 48 01 f1 48 c1 e9 0c 48 c1 e1 06 48 03 0d 4b 72 5c c8 48 8b 71 28 <0f> b6 4e 24 83 e1 0f 39 ca 0f 85 a7 02 00 00 f6 c4 08 74 26 80 7b
> RSP: 0018:ffffce128333f790 EFLAGS: 00010286
As noted in your response, I'm 99% certain this is the first derefence of the
shadow page in tdp_mmu_map_handle_target_level():
static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
struct kvm_page_fault *fault,
struct tdp_iter *iter)
{
struct kvm_mmu_page *sp = sptep_to_sp(rcu_dereference(iter->sptep));
u64 new_spte;
int ret = RET_PF_FIXED;
bool wrprot = false;
if (WARN_ON_ONCE(sp->role.level != fault->goal_level)) <============= "sp" is NULL
return RET_PF_RETRY;
The code stream lines up with that on my builds, and "role" is at offset 0x24.
I can think of three possible sources of failure:
1. KVM installed a non-leaf SPTE without doing set_page_private().
2. iter->sptep is corrupted/garbage.
3. iter->sptep points at a freed shadow page, i.e. page->private was nullified
due to the page being freed and/or re-allocated.
#1 seems unlikely as I wouldn't expect such a bug to manifest intermittently; the
code is pretty fixed/straightforward.
#2 isn't very likely either, given that it's dereferencing the shadow page that
fails. I.e. KVM did _not_ fail grabbing the shadow page from iter->sptep, then
iter->sptep isn't complete garbage. But it's still a possibility, e.g. if sptep
is garbage but happens to still point at a valid struct page.
#3 is the most likely option; as it would "just" require a violation of RCU
protection somewhere.
Can you run with this as a debug patch? With luck, the output will provide some
hint as to what's going wrong.
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 7b1102d26f9c..0332faf8ef9a 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -1174,6 +1174,17 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
int ret = RET_PF_FIXED;
bool wrprot = false;
+ if (WARN_ON_ONCE(!sp)) {
+ pr_warn("NULL sp. sptep = %lx, spte = %llx, pt[0] = %lx, pt[1] = %lx, pt[2] = %lx, pt[3] = %lx, pt[4] = %lx\n",
+ (unsigned long)iter->sptep, iter->old_spte,
+ (unsigned long)iter->pt_path[0],
+ (unsigned long)iter->pt_path[1],
+ (unsigned long)iter->pt_path[2],
+ (unsigned long)iter->pt_path[3],
+ (unsigned long)iter->pt_path[4]);
+ return RET_PF_RETRY;
+ }
+
if (WARN_ON_ONCE(sp->role.level != fault->goal_level))
return RET_PF_RETRY;
> Reproduction:
>
> The issue was observed under heavy host memory pressure while running
> a KVM guest (Android emulator via QEMU).
Can you elaborate on the environment? Specifically, what is your host setup?
E.g. CPU and platform info, and your .config.
> This has not been fully verified. Sending for maintainer review.
>
> Environment:
> Linux 6.19.10-arch1-1 x86_64
> GNU C 15.2.1
> Binutils 2.46
>
> Signed-off-by: punixcorn <ohyunwoods663@gmail.com>
next prev parent reply other threads:[~2026-04-08 14:18 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-08 10:29 [BUG] KVM: NULL pointer dereference in kvm_tdp_mmu_map under memory pressure punixcorn
2026-04-08 11:21 ` punixcorn
2026-04-08 14:18 ` Sean Christopherson [this message]
[not found] <202604081418.sean.christopherson@intel.com>
2026-04-08 15:36 ` punixcorn
2026-04-08 16:33 ` Sean Christopherson
[not found] <202604081633.sean.christopherson@intel.com>
2026-04-08 18:43 ` punixcorn
2026-04-13 21:47 ` Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=adZjswAhbcQmekxZ@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ohyunwoods663@gmail.com \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.