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] [thread-next>] [day] [month] [year] [list]
Message-Id: <97ae7b7bea8a22108aaebdfd9330de93ecc91333.1753865268.git.viresh.kumar@linaro.org>
Date: Wed, 30 Jul 2025 14:59:33 +0530
From: Viresh Kumar <viresh.kumar@...aro.org>
To: linux-kernel@...r.kernel.org,
	"Michael S. Tsirkin" <mst@...hat.com>,
	Jason Wang <jasowang@...hat.com>,
	Xuan Zhuo <xuanzhuo@...ux.alibaba.com>,
	Eugenio Pérez <eperezma@...hat.com>,
	Viresh Kumar <viresh.kumar@...aro.org>
Cc: Arnd Bergmann <arnd@...nel.org>,
	Vincent Guittot <vincent.guittot@...aro.org>,
	Alex Bennée <alex.bennee@...aro.org>,
	Bill Mills <bill.mills@...aro.org>,
	Rob Herring <robh@...nel.org>,
	Saravana Kannan <saravanak@...gle.com>,
	devicetree@...r.kernel.org,
	virtualization@...ts.linux.dev,
	Sudeep Holla <sudeep.holla@....com>,
	Bertrand Marquis <bertrand.marquis@....com>,
	"Edgar E . Iglesias" <edgar.iglesias@....com>,
	Arnaud Pouliquen <arnaud.pouliquen@...s.st.com>,
	Krzysztof Kozlowski <krzk+dt@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>
Subject: [RFC PATCH  4/6] virtio-msg: Add optional userspace interface for message I/O

Add support for an optional userspace interface to the virtio-msg
transport via a per-bus miscdevice. When enabled by a bus
implementation, this interface allows userspace to send and receive
virtio messages through a character device node.

A separate device node is created for each bus that registers for
userspace access, e.g., /dev/virtio-msg-N. This enables backend-side
components or test tools to interact with the transport layer directly
from userspace.

Bus implementations that do not require userspace interaction can omit
this interface entirely.

Signed-off-by: Viresh Kumar <viresh.kumar@...aro.org>
---
 drivers/virtio/Kconfig               |   8 ++
 drivers/virtio/Makefile              |   4 +-
 drivers/virtio/virtio_msg_internal.h |  32 ++++++
 drivers/virtio/virtio_msg_user.c     | 140 +++++++++++++++++++++++++++
 4 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 drivers/virtio/virtio_msg_user.c

diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 690ac98850b6..a86025c9e008 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -178,6 +178,14 @@ config VIRTIO_MSG
 	  This enables support for Virtio message transport. This option is
 	  selected by any driver which implements the virtio message bus.
 
+config VIRTIO_MSG_USER
+	tristate "Userspace interface for virtio message transport"
+	depends on VIRTIO_MSG
+	help
+	  This enables userspace interface for Virtio message transport. This
+	  can be used to read / write messages over virtio-msg transport from
+	  userspace.
+
 config VIRTIO_DMA_SHARED_BUFFER
 	tristate
 	depends on DMA_SHARED_BUFFER
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 3eff8ca72446..5b664c5f5f25 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -4,7 +4,9 @@ obj-$(CONFIG_VIRTIO_ANCHOR) += virtio_anchor.o
 obj-$(CONFIG_VIRTIO_PCI_LIB) += virtio_pci_modern_dev.o
 obj-$(CONFIG_VIRTIO_PCI_LIB_LEGACY) += virtio_pci_legacy_dev.o
 obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
-obj-$(CONFIG_VIRTIO_MSG) += virtio_msg.o
+virtio_msg_transport-y := virtio_msg.o
+virtio_msg_transport-$(CONFIG_VIRTIO_MSG_USER) += virtio_msg_user.o
+obj-$(CONFIG_VIRTIO_MSG) += virtio_msg_transport.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
 virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
diff --git a/drivers/virtio/virtio_msg_internal.h b/drivers/virtio/virtio_msg_internal.h
index b7c2cb44b67b..0d13d73507eb 100644
--- a/drivers/virtio/virtio_msg_internal.h
+++ b/drivers/virtio/virtio_msg_internal.h
@@ -9,6 +9,8 @@
 #ifndef _DRIVERS_VIRTIO_MSG_INTERNAL_H
 #define _DRIVERS_VIRTIO_MSG_INTERNAL_H
 
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
 #include <linux/virtio.h>
 #include <uapi/linux/virtio_msg.h>
 
@@ -53,4 +55,34 @@ void virtio_msg_unregister(struct virtio_msg_device *vmdev);
 void virtio_msg_prepare(struct virtio_msg *vmsg, u8 msg_id, u16 payload_size);
 int virtio_msg_event(struct virtio_msg_device *vmdev, struct virtio_msg *vmsg);
 
+/* Virtio msg userspace interface */
+struct virtio_msg_user_device;
+
+struct virtio_msg_user_ops {
+	int (*handle)(struct virtio_msg_user_device *vmudev, struct virtio_msg *vmsg);
+};
+
+/* Host side device using virtio message */
+struct virtio_msg_user_device {
+	struct virtio_msg_user_ops *ops;
+	struct miscdevice misc;
+	struct completion r_completion;
+	struct completion w_completion;
+	struct virtio_msg *vmsg;
+	struct device *parent;
+	char name[15];
+};
+
+#if IS_REACHABLE(CONFIG_VIRTIO_MSG_USER)
+int virtio_msg_user_register(struct virtio_msg_user_device *vmudev);
+void virtio_msg_user_unregister(struct virtio_msg_user_device *vmudev);
+#else
+static inline int virtio_msg_user_register(struct virtio_msg_user_device *vmudev)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void virtio_msg_user_unregister(struct virtio_msg_user_device *vmudev) {}
+#endif /* CONFIG_VIRTIO_MSG_USER */
+
 #endif /* _DRIVERS_VIRTIO_MSG_INTERNAL_H */
diff --git a/drivers/virtio/virtio_msg_user.c b/drivers/virtio/virtio_msg_user.c
new file mode 100644
index 000000000000..cf7286b3a311
--- /dev/null
+++ b/drivers/virtio/virtio_msg_user.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Virtio message transport user API.
+ *
+ * Copyright (C) 2025 Google LLC and Linaro.
+ * Viresh Kumar <viresh.kumar@...aro.org>
+ */
+
+#define pr_fmt(fmt) "virtio-msg: " fmt
+
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "virtio_msg_internal.h"
+
+#define to_virtio_msg_user_device(_misc) \
+	container_of(_misc, struct virtio_msg_user_device, misc)
+
+static ssize_t vmsg_miscdev_read(struct file *file, char __user *buf,
+				 size_t count, loff_t *pos)
+{
+	struct miscdevice *misc = file->private_data;
+	struct virtio_msg_user_device *vmudev = to_virtio_msg_user_device(misc);
+	struct device *dev = vmudev->parent;
+	int ret;
+
+	if (count < VIRTIO_MSG_MIN_SIZE) {
+		dev_err(dev, "Trying to read message of incorrect size: %zu\n",
+			count);
+		return 0;
+	}
+
+	/* Wait for the message */
+	ret = wait_for_completion_interruptible(&vmudev->r_completion);
+	if (ret < 0) {
+		dev_err(dev, "Interrupted while waiting for response: %d\n", ret);
+		return 0;
+	}
+
+	WARN_ON(!vmudev->vmsg);
+
+	/* The "vmsg" pointer is filled by the bus driver before waking up */
+	if (copy_to_user(buf, vmudev->vmsg, count) != 0)
+		return 0;
+
+	vmudev->vmsg = NULL;
+
+	return count;
+}
+
+static ssize_t vmsg_miscdev_write(struct file *file, const char __user *buf,
+				  size_t count, loff_t *pos)
+{
+	struct miscdevice *misc = file->private_data;
+	struct virtio_msg_user_device *vmudev = to_virtio_msg_user_device(misc);
+	struct virtio_msg *vmsg __free(kfree) = NULL;
+
+	if (count < VIRTIO_MSG_MIN_SIZE) {
+		dev_err(vmudev->parent, "Trying to write message of incorrect size: %zu\n",
+			count);
+		return 0;
+	}
+
+	vmsg = kzalloc(count, GFP_KERNEL);
+	if (!vmsg)
+		return 0;
+
+	if (copy_from_user(vmsg, buf, count) != 0)
+		return 0;
+
+	vmudev->ops->handle(vmudev, vmsg);
+
+	/* Wake up the handler only for responses */
+	if (vmsg->type & VIRTIO_MSG_TYPE_RESPONSE)
+		complete(&vmudev->w_completion);
+
+	return count;
+}
+
+static const struct file_operations vmsg_miscdev_fops = {
+	.owner = THIS_MODULE,
+	.read = vmsg_miscdev_read,
+	.write = vmsg_miscdev_write,
+};
+
+/**
+ * virtio_msg_user_register - Register a user-space accessible virtio message device
+ * @vmudev: Pointer to the virtio message user device
+ *
+ * Initializes and registers a user-accessible virtio message device as a `misc`
+ * character device. Upon successful registration, the device appears in
+ * userspace as `/dev/virtio-msg-N` where `N` is a unique identifier assigned at
+ * runtime.
+ *
+ * The resulting device node allows user-space interaction with the virtio
+ * message transport.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+int virtio_msg_user_register(struct virtio_msg_user_device *vmudev)
+{
+	static u8 vmsg_user_device_count;
+	int ret;
+
+	if (!vmudev || !vmudev->ops)
+		return -EINVAL;
+
+	init_completion(&vmudev->r_completion);
+	init_completion(&vmudev->w_completion);
+
+	vmudev->misc.parent = vmudev->parent;
+	vmudev->misc.minor = MISC_DYNAMIC_MINOR;
+	vmudev->misc.fops = &vmsg_miscdev_fops;
+	vmudev->misc.name = vmudev->name;
+	sprintf(vmudev->name, "virtio-msg-%d", vmsg_user_device_count);
+
+	ret = misc_register(&vmudev->misc);
+	if (ret)
+		return ret;
+
+	vmsg_user_device_count++;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_msg_user_register);
+
+/**
+ * virtio_msg_user_unregister - Unregister a user-space virtio message device
+ * @vmudev: Pointer to the virtio message user device
+ *
+ * Unregisters a previously registered virtio message device from the misc
+ * subsystem. This removes its user-space interface (e.g., /dev/virtio-msg-N).
+ */
+void virtio_msg_user_unregister(struct virtio_msg_user_device *vmudev)
+{
+	misc_deregister(&vmudev->misc);
+}
+EXPORT_SYMBOL_GPL(virtio_msg_user_unregister);
-- 
2.31.1.272.g89b43f80a514


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ