From: Valery Borovsky <vebohr@gmail.com>
To: seanjc@google.com, pbonzini@redhat.com
Cc: kvm@vger.kernel.org, linux-kselftest@vger.kernel.org,
shuah@kernel.org, linux-kernel@vger.kernel.org,
Valery Borovsky <vebohr@gmail.com>
Subject: [PATCH] KVM: selftests: verify toggling KVM_MEM_GUEST_MEMFD on an existing slot is rejected
Date: Wed, 5 Aug 2026 08:58:30 +0300 [thread overview]
Message-ID: <20260805055830.740175-1-vebohr@gmail.com> (raw)
set_memory_region_test covers creating a private memslot and rejecting
overlapping private regions, but nothing exercises a FLAGS_ONLY update
that toggles KVM_MEM_GUEST_MEMFD on a slot that already exists.
Add test_toggle_private_memory_region() to close that gap. It asserts
both directions are rejected with EINVAL:
1. clearing KVM_MEM_GUEST_MEMFD on a private slot;
2. setting KVM_MEM_GUEST_MEMFD on a slot created without it.
Both are enforced by the flags mask in kvm_set_memory_region():
(mem->flags ^ old->flags) & (KVM_MEM_READONLY | KVM_MEM_GUEST_MEMFD)
which gained KVM_MEM_GUEST_MEMFD in commit 9935df5333aa ("KVM: Disallow
toggling KVM_MEM_GUEST_MEMFD on an existing memslot"). Before that
commit, direction 1 freed the old slot without calling kvm_gmem_unbind(),
so closing the guest_memfd afterwards wrote to freed memory; the fix
commit records the resulting KASAN slab-use-after-free in
kvm_gmem_release().
The test runs only when KVM_X86_SW_PROTECTED_VM is available, alongside
the existing private-memslot tests.
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
---
Built and run on x86_64 against a 7.0 kernel; the new subtest passes.
.../selftests/kvm/set_memory_region_test.c | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c
index a152ab65c657..8fb2e7a96f6c 100644
--- a/tools/testing/selftests/kvm/set_memory_region_test.c
+++ b/tools/testing/selftests/kvm/set_memory_region_test.c
@@ -500,6 +500,50 @@ static void test_add_private_memory_region(void)
kvm_vm_free(vm);
}
+static void test_toggle_private_memory_region(void)
+{
+ struct kvm_vm *vm;
+ int memfd, r;
+
+ pr_info("Testing that toggling KVM_MEM_GUEST_MEMFD on existing slot is rejected\n");
+
+ vm = vm_create_barebones_type(KVM_X86_SW_PROTECTED_VM);
+ memfd = vm_create_guest_memfd(vm, MEM_REGION_SIZE, 0);
+
+ /* Create a private slot. */
+ vm_set_user_memory_region2(vm, MEM_REGION_SLOT, KVM_MEM_GUEST_MEMFD,
+ MEM_REGION_GPA, MEM_REGION_SIZE,
+ 0, memfd, 0);
+
+ /*
+ * Attempt a FLAGS_ONLY update that clears KVM_MEM_GUEST_MEMFD.
+ * Must fail with EINVAL. Before commit 9935df5333aa this caused
+ * a slab-use-after-free in kvm_gmem_release() because the old slot
+ * was freed without calling kvm_gmem_unbind().
+ */
+ r = __vm_set_user_memory_region2(vm, MEM_REGION_SLOT, 0,
+ MEM_REGION_GPA, MEM_REGION_SIZE,
+ 0, memfd, 0);
+ TEST_ASSERT(r == -1 && errno == EINVAL,
+ "Clearing KVM_MEM_GUEST_MEMFD should have failed with EINVAL, got r=%d errno=%d", r, errno);
+
+ /*
+ * Symmetrically, attempting to set KVM_MEM_GUEST_MEMFD on a slot
+ * that was created without it must also be rejected.
+ */
+ vm_set_user_memory_region(vm, MEM_REGION_SLOT + 1, 0,
+ MEM_REGION_GPA * 2, MEM_REGION_SIZE, NULL);
+ r = __vm_set_user_memory_region2(vm, MEM_REGION_SLOT + 1,
+ KVM_MEM_GUEST_MEMFD,
+ MEM_REGION_GPA * 2, MEM_REGION_SIZE,
+ 0, memfd, 0);
+ TEST_ASSERT(r == -1 && errno == EINVAL,
+ "Setting KVM_MEM_GUEST_MEMFD should have failed with EINVAL, got r=%d errno=%d", r, errno);
+
+ close(memfd);
+ kvm_vm_free(vm);
+}
+
static void test_add_overlapping_private_memory_regions(void)
{
struct kvm_vm *vm;
@@ -645,6 +689,7 @@ int main(int argc, char *argv[])
(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM))) {
test_add_private_memory_region();
test_add_overlapping_private_memory_regions();
+ test_toggle_private_memory_region();
} else {
pr_info("Skipping tests for KVM_MEM_GUEST_MEMFD memory regions\n");
}
--
2.53.0
next reply other threads:[~2026-08-05 5:58 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 5:58 Valery Borovsky [this message]
2026-08-05 6:10 ` [PATCH] KVM: selftests: verify toggling KVM_MEM_GUEST_MEMFD on an existing slot is rejected sashiko-bot
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=20260805055830.740175-1-vebohr@gmail.com \
--to=vebohr@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
/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.