@@ -385,13 +385,105 @@ static void test_add_max_memory_regions(void)
385385 kvm_vm_free (vm );
386386}
387387
388+
389+ #ifdef __x86_64__
390+ static void test_invalid_guest_memfd (struct kvm_vm * vm , int memfd ,
391+ size_t offset , const char * msg )
392+ {
393+ int r = __vm_set_user_memory_region2 (vm , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
394+ MEM_REGION_GPA , MEM_REGION_SIZE ,
395+ 0 , memfd , offset );
396+ TEST_ASSERT (r == -1 && errno == EINVAL , "%s" , msg );
397+ }
398+
399+ static void test_add_private_memory_region (void )
400+ {
401+ struct kvm_vm * vm , * vm2 ;
402+ int memfd , i ;
403+
404+ pr_info ("Testing ADD of KVM_MEM_GUEST_MEMFD memory regions\n" );
405+
406+ vm = vm_create_barebones_protected_vm ();
407+
408+ test_invalid_guest_memfd (vm , vm -> kvm_fd , 0 , "KVM fd should fail" );
409+ test_invalid_guest_memfd (vm , vm -> fd , 0 , "VM's fd should fail" );
410+
411+ memfd = kvm_memfd_alloc (MEM_REGION_SIZE , false);
412+ test_invalid_guest_memfd (vm , memfd , 0 , "Regular memfd() should fail" );
413+ close (memfd );
414+
415+ vm2 = vm_create_barebones_protected_vm ();
416+ memfd = vm_create_guest_memfd (vm2 , MEM_REGION_SIZE , 0 );
417+ test_invalid_guest_memfd (vm , memfd , 0 , "Other VM's guest_memfd() should fail" );
418+
419+ vm_set_user_memory_region2 (vm2 , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
420+ MEM_REGION_GPA , MEM_REGION_SIZE , 0 , memfd , 0 );
421+ close (memfd );
422+ kvm_vm_free (vm2 );
423+
424+ memfd = vm_create_guest_memfd (vm , MEM_REGION_SIZE , 0 );
425+ for (i = 1 ; i < PAGE_SIZE ; i ++ )
426+ test_invalid_guest_memfd (vm , memfd , i , "Unaligned offset should fail" );
427+
428+ vm_set_user_memory_region2 (vm , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
429+ MEM_REGION_GPA , MEM_REGION_SIZE , 0 , memfd , 0 );
430+ close (memfd );
431+
432+ kvm_vm_free (vm );
433+ }
434+
435+ static void test_add_overlapping_private_memory_regions (void )
436+ {
437+ struct kvm_vm * vm ;
438+ int memfd ;
439+ int r ;
440+
441+ pr_info ("Testing ADD of overlapping KVM_MEM_GUEST_MEMFD memory regions\n" );
442+
443+ vm = vm_create_barebones_protected_vm ();
444+
445+ memfd = vm_create_guest_memfd (vm , MEM_REGION_SIZE * 4 , 0 );
446+
447+ vm_set_user_memory_region2 (vm , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
448+ MEM_REGION_GPA , MEM_REGION_SIZE * 2 , 0 , memfd , 0 );
449+
450+ vm_set_user_memory_region2 (vm , MEM_REGION_SLOT + 1 , KVM_MEM_GUEST_MEMFD ,
451+ MEM_REGION_GPA * 2 , MEM_REGION_SIZE * 2 ,
452+ 0 , memfd , MEM_REGION_SIZE * 2 );
453+
454+ /*
455+ * Delete the first memslot, and then attempt to recreate it except
456+ * with a "bad" offset that results in overlap in the guest_memfd().
457+ */
458+ vm_set_user_memory_region2 (vm , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
459+ MEM_REGION_GPA , 0 , NULL , -1 , 0 );
460+
461+ /* Overlap the front half of the other slot. */
462+ r = __vm_set_user_memory_region2 (vm , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
463+ MEM_REGION_GPA * 2 - MEM_REGION_SIZE ,
464+ MEM_REGION_SIZE * 2 ,
465+ 0 , memfd , 0 );
466+ TEST_ASSERT (r == -1 && errno == EEXIST , "%s" ,
467+ "Overlapping guest_memfd() bindings should fail with EEXIST" );
468+
469+ /* And now the back half of the other slot. */
470+ r = __vm_set_user_memory_region2 (vm , MEM_REGION_SLOT , KVM_MEM_GUEST_MEMFD ,
471+ MEM_REGION_GPA * 2 + MEM_REGION_SIZE ,
472+ MEM_REGION_SIZE * 2 ,
473+ 0 , memfd , 0 );
474+ TEST_ASSERT (r == -1 && errno == EEXIST , "%s" ,
475+ "Overlapping guest_memfd() bindings should fail with EEXIST" );
476+
477+ close (memfd );
478+ kvm_vm_free (vm );
479+ }
480+ #endif
481+
388482int main (int argc , char * argv [])
389483{
390484#ifdef __x86_64__
391485 int i , loops ;
392- #endif
393486
394- #ifdef __x86_64__
395487 /*
396488 * FIXME: the zero-memslot test fails on aarch64 and s390x because
397489 * KVM_RUN fails with ENOEXEC or EFAULT.
@@ -402,6 +494,14 @@ int main(int argc, char *argv[])
402494 test_add_max_memory_regions ();
403495
404496#ifdef __x86_64__
497+ if (kvm_has_cap (KVM_CAP_GUEST_MEMFD ) &&
498+ (kvm_check_cap (KVM_CAP_VM_TYPES ) & BIT (KVM_X86_SW_PROTECTED_VM ))) {
499+ test_add_private_memory_region ();
500+ test_add_overlapping_private_memory_regions ();
501+ } else {
502+ pr_info ("Skipping tests for KVM_MEM_GUEST_MEMFD memory regions\n" );
503+ }
504+
405505 if (argc > 1 )
406506 loops = atoi_positive ("Number of iterations" , argv [1 ]);
407507 else
0 commit comments