lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250928190624.3735830-16-skhawaja@google.com>
Date: Sun, 28 Sep 2025 19:06:23 +0000
From: Samiullah Khawaja <skhawaja@...gle.com>
To: David Woodhouse <dwmw2@...radead.org>, Lu Baolu <baolu.lu@...ux.intel.com>, 
	Joerg Roedel <joro@...tes.org>, Will Deacon <will@...nel.org>, 
	Pasha Tatashin <pasha.tatashin@...een.com>, Jason Gunthorpe <jgg@...pe.ca>, iommu@...ts.linux.dev
Cc: Samiullah Khawaja <skhawaja@...gle.com>, Robin Murphy <robin.murphy@....com>, 
	Pratyush Yadav <pratyush@...nel.org>, Kevin Tian <kevin.tian@...el.com>, linux-kernel@...r.kernel.org, 
	Saeed Mahameed <saeedm@...dia.com>, Adithya Jayachandran <ajayachandra@...dia.com>, 
	Parav Pandit <parav@...dia.com>, Leon Romanovsky <leonro@...dia.com>, William Tu <witu@...dia.com>, 
	Vipin Sharma <vipinsh@...gle.com>, dmatlack@...gle.com, zhuyifei@...gle.com, 
	Chris Li <chrisl@...nel.org>, praan@...gle.com
Subject: [RFC PATCH 15/15] iommufd/selftest: Add test to verify iommufd preservation

Test iommufd preservation by setting up an iommufd and preserve it
across live update. Test takes VFIO cdev path of a device bound to
vfio-pci driver and binds it to an iommufd being preserved.

Note that the helper functions setup_cdev, open_iommufd, and
setup_iommufd will be replaced with VFIO selftest library. Similarly the
helper function defined to open and interface with Live Update
Orchestrator device will be replaced with a common helper library.

Signed-off-by: Samiullah Khawaja <skhawaja@...gle.com>
---
 tools/testing/selftests/iommu/Makefile        |   1 +
 .../selftests/iommu/iommufd_liveupdate.c      | 196 ++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 tools/testing/selftests/iommu/iommufd_liveupdate.c

diff --git a/tools/testing/selftests/iommu/Makefile b/tools/testing/selftests/iommu/Makefile
index 84abeb2f0949..42c962c5e612 100644
--- a/tools/testing/selftests/iommu/Makefile
+++ b/tools/testing/selftests/iommu/Makefile
@@ -6,5 +6,6 @@ LDLIBS += -lcap
 TEST_GEN_PROGS :=
 TEST_GEN_PROGS += iommufd
 TEST_GEN_PROGS += iommufd_fail_nth
+TEST_GEN_PROGS += iommufd_liveupdate
 
 include ../lib.mk
diff --git a/tools/testing/selftests/iommu/iommufd_liveupdate.c b/tools/testing/selftests/iommu/iommufd_liveupdate.c
new file mode 100644
index 000000000000..1003d0cf2cae
--- /dev/null
+++ b/tools/testing/selftests/iommu/iommufd_liveupdate.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (c) 2025, Google LLC.
+ * Samiullah Khawaja <skhawaja@...gle.com>
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#define __EXPORTED_HEADERS__
+#include <linux/liveupdate.h>
+#include <linux/iommufd.h>
+#include <linux/types.h>
+#include <linux/vfio.h>
+
+#include "../kselftest.h"
+
+#define ksft_assert(condition) \
+	do { if (!(condition)) \
+	ksft_exit_fail_msg("Failed: %s at %s %d\n", \
+	#condition, __FILE__, __LINE__); } while (0)
+
+int setup_cdev(const char *vfio_cdev_path)
+{
+	int cdev_fd;
+
+	cdev_fd = open(vfio_cdev_path, O_RDWR);
+	if (cdev_fd < 0)
+		ksft_exit_skip("Failed to open VFIO cdev: %s\n", vfio_cdev_path);
+
+	return cdev_fd;
+}
+
+int open_iommufd(void)
+{
+	int iommufd;
+
+	iommufd = open("/dev/iommu", O_RDWR);
+	if (iommufd < 0)
+		ksft_exit_skip("Failed to open /dev/iommu. IOMMUFD support not enabled.\n");
+
+	return iommufd;
+}
+
+int setup_iommufd(int iommufd, int cdev_fd)
+{
+	int ret;
+
+	struct vfio_device_bind_iommufd bind = {
+		.argsz = sizeof(bind),
+		.flags = 0,
+	};
+	struct iommu_ioas_alloc alloc_data  = {
+		.size = sizeof(alloc_data),
+		.flags = 0,
+	};
+	struct vfio_device_attach_iommufd_pt attach_data = {
+		.argsz = sizeof(attach_data),
+		.flags = 0,
+	};
+
+	bind.iommufd = iommufd;
+	ret = ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, &bind);
+	ksft_assert(!ret);
+
+	ret = ioctl(iommufd, IOMMU_IOAS_ALLOC, &alloc_data);
+	ksft_assert(!ret);
+
+	attach_data.pt_id = alloc_data.out_ioas_id;
+	ret = ioctl(cdev_fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data);
+	ksft_assert(!ret);
+
+	return ret;
+}
+
+int open_liveupdate_orchestrator(void)
+{
+	int luo;
+
+	luo = open("/dev/liveupdate", O_RDWR);
+	ksft_assert(luo > 0);
+
+	return luo;
+}
+
+__u32 liveupdate_get_state(int luo)
+{
+	struct liveupdate_ioctl_get_state state;
+	int ret;
+
+	state.size = sizeof(state);
+	ret = ioctl(luo, LIVEUPDATE_IOCTL_GET_STATE, &state);
+	ksft_assert(!ret);
+
+	return state.state;
+}
+
+bool liveupdate_state_normal(int luo)
+{
+	return liveupdate_get_state(luo) == LIVEUPDATE_STATE_NORMAL;
+}
+
+bool liveupdate_state_updated(int luo)
+{
+	return liveupdate_get_state(luo) == LIVEUPDATE_STATE_UPDATED;
+}
+
+int liveupdate_set_event(int luo, enum liveupdate_event ev)
+{
+	struct liveupdate_ioctl_set_event event;
+	int ret;
+
+	event.event = ev;
+	event.size = sizeof(event);
+
+	ret = ioctl(luo, LIVEUPDATE_IOCTL_SET_EVENT, &event);
+	ksft_assert(!ret);
+
+	return ret;
+}
+
+int liveupdate_preserve_iommufd(int luo, int iommufd, int token)
+{
+	struct liveupdate_ioctl_fd_preserve preserve;
+	int ret;
+
+	preserve.fd = iommufd;
+	preserve.token = token;
+	preserve.size = sizeof(preserve);
+
+	ret = ioctl(luo, LIVEUPDATE_IOCTL_FD_PRESERVE, &preserve);
+	ksft_assert(!ret);
+
+	return ret;
+}
+
+int liveupdate_restore_iommufd(int luo, int token)
+{
+	struct liveupdate_ioctl_fd_restore restore;
+	int ret;
+
+	restore.token = token;
+	restore.size = sizeof(restore);
+
+	ret = ioctl(luo, LIVEUPDATE_IOCTL_FD_RESTORE, &restore);
+	ksft_assert(!ret);
+	ksft_assert(restore.fd > 0);
+
+	return restore.fd;
+}
+
+int main(int argc, char *argv[])
+{
+	int iommufd, cdev_fd, luo, ret;
+	const int token = 0x123456;
+
+	if (argc < 2) {
+		printf("Usage: ./iommufd_liveupdate <vfio_cdev_path>\n");
+		return 1;
+	}
+
+	cdev_fd = setup_cdev(argv[1]);
+
+	luo = open_liveupdate_orchestrator();
+	ksft_assert(luo > 0);
+
+	if (liveupdate_state_normal(luo))
+		iommufd = open_iommufd();
+	else if (liveupdate_state_updated(luo))
+		iommufd = liveupdate_restore_iommufd(luo, token);
+	else
+		ksft_exit_fail_msg("Test can only run when LUO state is normal or updated");
+
+	ret = setup_iommufd(iommufd, cdev_fd);
+	ksft_assert(!ret);
+
+	if (liveupdate_state_normal(luo)) {
+		ret = liveupdate_preserve_iommufd(luo, iommufd, token);
+		ksft_assert(!ret);
+
+		ret = liveupdate_set_event(luo, LIVEUPDATE_PREPARE);
+		ksft_assert(!ret);
+
+		while (1)
+			sleep(5);
+	} else {
+		ret = liveupdate_set_event(luo, LIVEUPDATE_FINISH);
+		ksft_assert(!ret);
+	}
+
+	return 0;
+}
+
-- 
2.51.0.536.g15c5d4f767-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ