Subject: Re: [BUG] NULL pointer dereference in sev_writeback_caches during KVM SEV migration kselftest on AMD platform

From: Sean Christopherson <[email-masked]>
Date: Mon, 14 Jul 2025 08:14:44 -0700

On Mon, Jul 14, 2025, Zheyun Shen wrote:
> The problem is triggered by the following codes in tools/testing/selftests/kvm/x86/sev_migrate_tests.c:
> static void test_sev_migrate_from(bool es)
> {
> 	struct kvm_vm *src_vm;
> 	struct kvm_vm *dst_vms[NR_MIGRATE_TEST_VMS];
> 	int i, ret;
> 
> 	src_vm = sev_vm_create(es);
> 	for (i = 0; i < NR_MIGRATE_TEST_VMS; ++i)
> 		dst_vms[i] = aux_vm_create(true);
> 
> 	/* Initial migration from the src to the first dst. */
> 	sev_migrate_from(dst_vms[0], src_vm);
> 
> 	for (i = 1; i < NR_MIGRATE_TEST_VMS; i++)
> 		sev_migrate_from(dst_vms[i], dst_vms[i - 1]);
> 
> 	/* Migrate the guest back to the original VM. */
> 	ret = __sev_migrate_from(src_vm, dst_vms[NR_MIGRATE_TEST_VMS - 1]);
> 	TEST_ASSERT(ret == -1 && errno == EIO,
> 		    "VM that was migrated from should be dead. ret %d, errno: %d", ret,
> 		    errno);
> 
> 	kvm_vm_free(src_vm);
> 	for (i = 0; i < NR_MIGRATE_TEST_VMS; ++i)
> 		kvm_vm_free(dst_vms[i]);
> }
> 
> I add some logs in kvm and following shows the result:
> [   51.618135] sev guest init kvm:ff177f272432e000                                                                                  

Argh, I forgot that sev_vm_move_enc_context_from() requires the destination to
*not* be an SEV guest.  KVM needs to explicitly copy over the stack.

> [   51.627235] kvm destory vm kvm:ff177f272432e000                                                                                   
> [   51.628011] kvm destory vm mmu notifier unregister kvm:ff177f272432e000                                                          
> [   51.642840] kvm destory vm arch destory vm kvm:ff177f272432e000                                                                  
> [   51.673612] vm destory x86                                                                                                       
> [   51.673957] svm vm destory                                                                                                       
> [   51.674401] kvm destory vm kvm:ff177f272432c000                                                                                   
> [   51.675152] kvm destory vm mmu notifier unregister kvm:ff177f272432c000                                                          
> [   51.675981] kvm destory vm arch destory vm kvm:ff177f272432c000                                                                  
> [   51.715937] vm destory x86                                                                                                       
> [   51.716289] svm vm destory                                                                                                       
> [   51.716754] kvm destory vm kvm:ff177f272432a000                                                                                   
> [   51.717530] kvm destory vm mmu notifier unregister kvm:ff177f272432a000                                                          
> [   51.718363] kvm destory vm arch destory vm kvm:ff177f272432a000                                                                  
> [   51.746672] vm destory x86
> [   51.747018] svm vm destory
> [   51.747454] kvm destory vm kvm:ff177f2724328000
> [   51.748219] kvm destory vm mmu notifier unregister kvm:ff177f2724328000
> [   51.749033] BUG: kernel NULL pointer dereference, address: 0000000000000000
> [   51.749885] #PF: supervisor read access in kernel mode
> [   51.750519] #PF: error_code(0x0000) - not-present page
> 
> It seems that the cpumask structure is not transferred correctly from
> ff177f272432e000 to ff177f2724328000.  But unfortunately I’m not familiar
> with SEV migration. I need to spend some time looking into how SEV migration
> works in order to solve this issue.

...

> >> I can reproduce this issue in my environment, and I will try to resolve it as
> >> soon as possible.
> > 
> > Phew, that's good, because I can't repro this, and I don't see anything obviously
> > wrong.

/facepalm

-ENOCOFFEE.  I was conflating CONFIG_VMAP_STACK with CONFIG_CPUMASK_OFFSTACK and
thus testing the wrong thing.

I think this is the fix, testing now...

diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 95668e84ab86..1476e877b2dc 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1936,6 +1936,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
        dst->enc_context_owner = src->enc_context_owner;
        dst->es_active = src->es_active;
        dst->vmsa_features = src->vmsa_features;
+       memcpy(&dst->have_run_cpus, &src->have_run_cpus, sizeof(src->have_run_cpus));
 
        src->asid = 0;
        src->active = false;
@@ -1943,6 +1944,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
        src->pages_locked = 0;
        src->enc_context_owner = NULL;
        src->es_active = false;
+       memset(&src->have_run_cpus, 0, sizeof(src->have_run_cpus));
 
        list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list);