]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: selftests: Add guest_memfd regression test signed offset+size bug
authorSean Christopherson <seanjc@google.com>
Tue, 2 Jun 2026 17:09:21 +0000 (10:09 -0700)
committerSean Christopherson <seanjc@google.com>
Wed, 3 Jun 2026 12:39:24 +0000 (05:39 -0700)
Add a regression (and proof-of-bug) testcase to ensure KVM rejects an
offset+size that would result in a negative value when computed as a signed
64-bit value.  KVM had a flaw where it would allow binding a memslot to a
guest_memfd instance even with a wildly out-of-range offset, if the offset
and size were both positive values, but the combined offset+size was
negative.

Use "0x7fffffffffffffffull - page_size", i.e. "INT64_MAX - page_size", for
the offset as the size of the guest_memfd file must be at least page_size
(KVM requires memslots and gmem files to be host page-size aligned).  I.e.
"INT64_MAX - page_size + size" is guaranteed to generate an offset+size
that is negative when converted to a signed 64-bit value *and* honors KVM's
alignment requirements.

Reviewed-by: Ackerley Tng <ackerleytng@google.com>
Tested-by: Ackerley Tng <ackerleytng@google.com>
Link: https://patch.msgid.link/20260602170921.1304394-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/guest_memfd_test.c

index 4b4462c8bacdfde66cb0c124a77e8236acedc965..775f99443d4985c42595bdd722b082723a3fc34b 100644 (file)
@@ -345,6 +345,16 @@ static void test_invalid_punch_hole(int fd, size_t total_size)
        }
 }
 
+static void test_invalid_binding(struct kvm_vm *vm, int fd, size_t size)
+{
+       int r;
+
+       r = __vm_set_user_memory_region2(vm, 0, KVM_MEM_GUEST_MEMFD, 0, size, 0,
+                                        fd, ALIGN_DOWN(INT64_MAX, page_size));
+       TEST_ASSERT(r && errno == EINVAL,
+                   "Memslot with out-of-range offset+size should fail");
+}
+
 static void test_create_guest_memfd_invalid_sizes(struct kvm_vm *vm,
                                                  u64 guest_memfd_flags)
 {
@@ -456,6 +466,7 @@ static void __test_guest_memfd(struct kvm_vm *vm, u64 flags)
        gmem_test(file_size, vm, flags);
        gmem_test(fallocate, vm, flags);
        gmem_test(invalid_punch_hole, vm, flags);
+       gmem_test_vm(invalid_binding, vm, flags);
 }
 
 static void test_guest_memfd(unsigned long vm_type)