All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Iván Ezequiel Rodriguez" <ivanrwcm25@gmail.com>
To: pbonzini@redhat.com, seanjc@google.com
Cc: kvm@vger.kernel.org, linux-kselftest@lists.kernel.org,
	"Iván Ezequiel Rodriguez" <ivanrwcm25@gmail.com>
Subject: [PATCH 1/1] kvm: reject unknown flags in device and dirty-log ioctls
Date: Wed,  1 Jul 2026 16:49:46 -0300	[thread overview]
Message-ID: <20260701194946.768731-2-ivanrwcm25@gmail.com> (raw)
In-Reply-To: <20260701194946.768731-1-ivanrwcm25@gmail.com>

KVM_CREATE_DEVICE only defines KVM_CREATE_DEVICE_TEST, but unknown
flag bits were silently ignored. kvm_device_attr.flags is documented
as unused yet was never checked centrally. KVM_ENABLE_CAP for
KVM_CAP_DIRTY_LOG_RING and KVM_CAP_DIRTY_LOG_RING_ACQ_REL requires
cap->flags to be zero per api.rst, but the generic handler did not
enforce it.

Reject unknown or non-zero flags with -EINVAL, consistent with other
KVM ioctls and dma-heap flag validation. Add a selftest covering all
three paths.

Signed-off-by: Iván Ezequiel Rodriguez <ivanrwcm25@gmail.com>
---
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../kvm/ioctl_flag_validation_test.c          | 104 ++++++++++++++++++
 virt/kvm/kvm_main.c                           |   9 ++
 3 files changed, 114 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/ioctl_flag_validation_test.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index d28a057fa6c2..38c78838318c 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -59,6 +59,7 @@ TEST_PROGS_x86 += x86/nx_huge_pages_test.sh
 TEST_GEN_PROGS_COMMON = demand_paging_test
 TEST_GEN_PROGS_COMMON += dirty_log_test
 TEST_GEN_PROGS_COMMON += guest_print_test
+TEST_GEN_PROGS_COMMON += ioctl_flag_validation_test
 TEST_GEN_PROGS_COMMON += irqfd_test
 TEST_GEN_PROGS_COMMON += kvm_binary_stats_test
 TEST_GEN_PROGS_COMMON += kvm_create_max_vcpus
diff --git a/tools/testing/selftests/kvm/ioctl_flag_validation_test.c b/tools/testing/selftests/kvm/ioctl_flag_validation_test.c
new file mode 100644
index 000000000000..30c22435bb14
--- /dev/null
+++ b/tools/testing/selftests/kvm/ioctl_flag_validation_test.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test that selected KVM ioctls reject unknown flag bits with -EINVAL.
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+
+static void test_create_device_unknown_flags(struct kvm_vm *vm)
+{
+	struct kvm_create_device cd = {
+		.type = KVM_DEV_TYPE_VFIO,
+		.flags = 0x2,
+	};
+	int r;
+
+	TEST_REQUIRE(kvm_check_cap(KVM_CAP_DEVICE_CTRL));
+
+	r = __vm_ioctl(vm, KVM_CREATE_DEVICE, &cd);
+	TEST_ASSERT(r == -1 && errno == EINVAL,
+		    "KVM_CREATE_DEVICE with unknown flags");
+
+	cd.flags = KVM_CREATE_DEVICE_TEST | 0x2;
+	r = __vm_ioctl(vm, KVM_CREATE_DEVICE, &cd);
+	TEST_ASSERT(r == -1 && errno == EINVAL,
+		    "KVM_CREATE_DEVICE TEST with unknown flags");
+}
+
+static void test_device_attr_flags(struct kvm_vm *vm)
+{
+	struct kvm_device_attr attr = {
+		.flags = 1,
+		.group = KVM_DEV_VFIO_FILE,
+		.attr = KVM_DEV_VFIO_FILE_ADD,
+		.addr = 0,
+	};
+	int dev_fd, r;
+
+	TEST_REQUIRE(kvm_check_cap(KVM_CAP_DEVICE_CTRL));
+
+	dev_fd = __kvm_create_device(vm, KVM_DEV_TYPE_VFIO);
+	if (dev_fd < 0) {
+		pr_info("Skipping device_attr test, KVM_DEV_TYPE_VFIO unavailable\n");
+		return;
+	}
+
+	r = __kvm_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attr);
+	TEST_ASSERT(r == -1 && errno == EINVAL,
+		    "KVM_HAS_DEVICE_ATTR with unknown flags");
+
+	close(dev_fd);
+}
+
+static void test_dirty_log_ring_cap_flags(struct kvm_vm *vm)
+{
+	struct kvm_enable_cap cap = {
+		.flags = 1,
+		.args = { 4096 },
+	};
+	int r;
+
+	if (!kvm_has_cap(KVM_CAP_DIRTY_LOG_RING) &&
+	    !kvm_has_cap(KVM_CAP_DIRTY_LOG_RING_ACQ_REL)) {
+		pr_info("Skipping dirty log ring cap flag test, cap unavailable\n");
+		return;
+	}
+
+	if (kvm_has_cap(KVM_CAP_DIRTY_LOG_RING)) {
+		cap.cap = KVM_CAP_DIRTY_LOG_RING;
+		cap.flags = 1;
+		r = __vm_ioctl(vm, KVM_ENABLE_CAP, &cap);
+		TEST_ASSERT(r == -1 && errno == EINVAL,
+			    "KVM_ENABLE_CAP DIRTY_LOG_RING with unknown flags");
+	}
+
+	if (kvm_has_cap(KVM_CAP_DIRTY_LOG_RING_ACQ_REL)) {
+		cap.cap = KVM_CAP_DIRTY_LOG_RING_ACQ_REL;
+		cap.flags = 1;
+		r = __vm_ioctl(vm, KVM_ENABLE_CAP, &cap);
+		TEST_ASSERT(r == -1 && errno == EINVAL,
+			    "KVM_ENABLE_CAP DIRTY_LOG_RING_ACQ_REL with unknown flags");
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	struct kvm_vm *vm;
+
+	vm = vm_create_barebones();
+
+	test_create_device_unknown_flags(vm);
+	test_device_attr_flags(vm);
+	test_dirty_log_ring_cap_flags(vm);
+
+	kvm_vm_free(vm);
+	return 0;
+}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index e44c20c04961..a2aecc06ab67 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4719,6 +4719,9 @@ static int kvm_device_ioctl_attr(struct kvm_device *dev,
 	if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
 		return -EFAULT;
 
+	if (attr.flags)
+		return -EINVAL;
+
 	return accessor(dev, &attr);
 }
 
@@ -4811,6 +4814,9 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
 	int type;
 	int ret;
 
+	if (cd->flags & ~KVM_CREATE_DEVICE_TEST)
+		return -EINVAL;
+
 	if (cd->type >= ARRAY_SIZE(kvm_device_ops_table))
 		return -ENODEV;
 
@@ -5061,6 +5067,9 @@ static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm,
 		if (!kvm_vm_ioctl_check_extension_generic(kvm, cap->cap))
 			return -EINVAL;
 
+		if (cap->flags)
+			return -EINVAL;
+
 		return kvm_vm_ioctl_enable_dirty_log_ring(kvm, cap->args[0]);
 	case KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP: {
 		int r = -EINVAL;
-- 
2.43.0


  reply	other threads:[~2026-07-01 19:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-01 19:49 [PATCH 0/1] kvm: reject unknown flags in device and dirty-log ioctls Iván Ezequiel Rodriguez
2026-07-01 19:49 ` Iván Ezequiel Rodriguez [this message]
2026-07-01 20:09   ` [PATCH 1/1] " 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=20260701194946.768731-2-ivanrwcm25@gmail.com \
    --to=ivanrwcm25@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kselftest@lists.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.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.