[PATCH 1/2] ioctl: add a stub for decoding vhost related ioctls

Daniel Cohen Hillel danielcohenhillel at gmail.com
Sun Oct 22 00:43:55 UTC 2023


* vhost.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* configure.ac (AC_CHECK_HEADERS): Add linux/vhost.h.
* defs.h (kvm_ioctl): New prototype.
* ioctl.c (ioctl_decode) HAVE_LINUX_VHOST_H]: Use vhost_ioctl.
---
 configure.ac    |  1 +
 src/Makefile.am |  1 +
 src/defs.h      |  1 +
 src/ioctl.c     |  4 ++++
 src/vhost.c     | 25 +++++++++++++++++++++++++
 5 files changed, 32 insertions(+)
 create mode 100644 src/vhost.c

diff --git a/configure.ac b/configure.ac
index 125f37208..0649c55f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -467,6 +467,7 @@ AC_CHECK_HEADERS(m4_normalize([
 AC_CHECK_HEADERS(m4_normalize([
 	linux/ipc.h
 	linux/kvm.h
+	linux/vhost.h
 ]),,, [AC_INCLUDES_DEFAULT
 #include <linux/types.h>
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 6bd12eb60..098479f22 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -395,6 +395,7 @@ libstrace_a_SOURCES =	\
 	utime.c		\
 	utimes.c	\
 	v4l2.c		\
+	vhost.c		\
 	wait.c		\
 	wait.h		\
 	watchdog_ioctl.c \
diff --git a/src/defs.h b/src/defs.h
index 811d2d850..27d2105d3 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -1447,6 +1447,7 @@ DECL_IOCTL(tee);
 DECL_IOCTL(term);
 DECL_IOCTL(ubi);
 DECL_IOCTL(uffdio);
+DECL_IOCTL(vhost);
 DECL_IOCTL(watchdog);
 # undef DECL_IOCTL
 
diff --git a/src/ioctl.c b/src/ioctl.c
index fc6cef933..58635df6d 100644
--- a/src/ioctl.c
+++ b/src/ioctl.c
@@ -425,6 +425,10 @@ ioctl_decode(struct tcb *tcp, const struct finfo *finfo)
 #ifdef HAVE_LINUX_KVM_H
 	case 0xae:
 		return kvm_ioctl(tcp, code, arg);
+#endif
+#ifdef HAVE_LINUX_VHOST_H
+	case 0xaf:
+		return vhost_ioctl(tcp, code, arg);
 #endif
 	case 0xb4:
 		return gpio_ioctl(tcp, code, arg);
diff --git a/src/vhost.c b/src/vhost.c
new file mode 100644
index 000000000..5df77e039
--- /dev/null
+++ b/src/vhost.c
@@ -0,0 +1,25 @@
+/*
+ * Support for decoding of VHOST_* ioctl commands.
+ *
+ * Copyright (c) 2023 Daniel Cohen Hillel <danielcohenhillel at gmail.com>
+ * Copyright (c) 2023 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+
+#ifdef HAVE_LINUX_VHOST_H
+# include <linux/vhost.h>
+
+int
+vhost_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
+{
+	switch (code) {
+	default:
+		return RVAL_DECODED;
+	}
+}
+
+#endif /* HAVE_LINUX_VHOST_H */
\ No newline at end of file
-- 
2.34.1


>From 2e85282a9547269fdf8df98609fbe83ef3084c03 Mon Sep 17 00:00:00 2001
From: Daniel Cohen Hillel <danielcohenhillel at gmail.com>
Date: Sun, 22 Oct 2023 03:30:10 +0300
Subject: [PATCH 2/2] vhost: decode arguments of various VHOST_* ioctls

* configure.ac (AC_CHECK_TYPES): Add structs under `linux/vhost_types.h`:
          	struct vhost_vring_file,
	        struct vhost_vring_state,
	        struct vhost_vring_addr,
	        struct vhost_memory,
	        struct vhost_memory_region
* xlat/vhost_vring_flags.in: New file.
* vhost.c:
 [HAVE_STRUCT_VHOST_VRING_FILE]: vhost_ioctl_decode_vring_file: New function.
 [HAVE_STRUCT_VHOST_VRING_STATE]: vhost_ioctl_decode_vring_state: New function.
 [HAVE_STRUCT_VHOST_VRING_ADDR]:
     include "xlat/vhost_vring_flags.h"
     and vhost_ioctl_decode_vring_set_addr: New function.
 [HAVE_STRUCT_VHOST_MEMORY, HAVE_STRUCT_VHOST_MEMORY_REGION]:
         print_vhost_memory_region, vhost_ioctl_decode_set_mem_table: New functions
(vhost_ioctl): Added new functions to the switch case (under correct ifdefs)
* List of new supported ioctls:
    - VHOST_SET_VRING_KICK
    - VHOST_SET_VRING_CALL
    - VHOST_SET_VRING_ERR
    - VHOST_NET_SET_BACKEND
    - VHOST_SET_VRING_NUM
    - VHOST_SET_VRING_BASE
    - VHOST_GET_VRING_BASE
    - VHOST_SET_VRING_ENDIAN
    - VHOST_GET_VRING_ENDIAN
    - VHOST_SET_VRING_BUSYLOOP_TIMEOUT
    - VHOST_GET_VRING_BUSYLOOP_TIMEOUT
    - VHOST_VDPA_SET_VRING_ENABLE
    - VHOST_SET_VRING_ADDR
    - VHOST_SET_MEM_TABLE
---
 configure.ac                  |   8 ++
 src/vhost.c                   | 180 ++++++++++++++++++++++++++++++++++
 src/xlat/vhost_vring_flags.in |   1 +
 3 files changed, 189 insertions(+)
 create mode 100644 src/xlat/vhost_vring_flags.in

diff --git a/configure.ac b/configure.ac
index 0649c55f0..73da08ae2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -546,6 +546,14 @@ AC_CHECK_TYPES(m4_normalize([
 	struct kvm_ioeventfd
 ]),,, [#include <linux/kvm.h>])
 
+AC_CHECK_TYPES(m4_normalize([
+	struct vhost_vring_file,
+	struct vhost_vring_state,
+	struct vhost_vring_addr,
+	struct vhost_memory,
+	struct vhost_memory_region
+]),,, [#include <linux/vhost_types.h>])
+
 AC_CHECK_TYPES(m4_normalize([
 	struct sockaddr_alg_new
 ]),,, [#include <netinet/in.h>
diff --git a/src/vhost.c b/src/vhost.c
index 5df77e039..42f1aa1ec 100644
--- a/src/vhost.c
+++ b/src/vhost.c
@@ -13,10 +13,190 @@
 #ifdef HAVE_LINUX_VHOST_H
 # include <linux/vhost.h>
 
+# ifdef HAVE_STRUCT_VHOST_VRING_FILE
+static int
+vhost_ioctl_decode_vring_file(struct tcb *const tcp, const unsigned int code,
+		       const kernel_ulong_t arg)
+{
+    struct vhost_vring_file f;
+
+    if (entering(tcp) && (
+           code == VHOST_GET_VRING_BASE
+        || code == VHOST_GET_VRING_ENDIAN
+        || code == VHOST_GET_VRING_BUSYLOOP_TIMEOUT)) {
+            return 0;
+    }
+
+	tprint_arg_next();
+
+	if (umove_or_printaddr(tcp, arg, &f))
+		return RVAL_IOCTL_DECODED;
+
+	tprint_struct_begin();
+
+	PRINT_FIELD_U(f, index);
+	tprint_struct_next();
+	PRINT_FIELD_FD(f, fd, tcp);
+
+	tprint_struct_end();
+
+	return RVAL_IOCTL_DECODED;
+}
+# endif /* HAVE_STRUCT_VHOST_VRING_FILE */
+
+# ifdef HAVE_STRUCT_VHOST_VRING_STATE
+static int
+vhost_ioctl_decode_vring_state(struct tcb *const tcp, const unsigned int code,
+		       const kernel_ulong_t arg)
+{
+    struct vhost_vring_state s;
+
+	tprint_arg_next();
+
+	if (umove_or_printaddr(tcp, arg, &s))
+		return RVAL_IOCTL_DECODED;
+
+	tprint_struct_begin();
+
+	PRINT_FIELD_U(s, index);
+	tprint_struct_next();
+	PRINT_FIELD_U(s, num);
+
+	tprint_struct_end();
+
+	return RVAL_IOCTL_DECODED;
+}
+# endif /* HAVE_STRUCT_VHOST_VRING_STATE */
+
+# ifdef HAVE_STRUCT_VHOST_VRING_ADDR
+#  include "xlat/vhost_vring_flags.h"
+static int
+vhost_ioctl_decode_vring_set_addr(struct tcb *const tcp, const unsigned int code,
+		       const kernel_ulong_t arg)
+{
+    struct vhost_vring_addr addr;
+
+	tprint_arg_next();
+
+	if (umove_or_printaddr(tcp, arg, &addr))
+		return RVAL_IOCTL_DECODED;
+
+	tprint_struct_begin();
+
+	PRINT_FIELD_U(addr, index);
+	tprint_struct_next();
+	PRINT_FIELD_FLAGS(addr, flags, vhost_vring_flags, "VHOST_VRING_F_???");
+	tprint_struct_next();
+	PRINT_FIELD_X(addr, desc_user_addr);
+	tprint_struct_next();
+	PRINT_FIELD_X(addr, used_user_addr);
+	tprint_struct_next();
+	PRINT_FIELD_X(addr, avail_user_addr);
+    if (addr.flags & VHOST_VRING_F_LOG) {
+        tprint_struct_next();
+        PRINT_FIELD_X(addr, log_guest_addr);
+    }
+
+	tprint_struct_end();
+
+	return RVAL_IOCTL_DECODED;
+}
+# endif /* HAVE_STRUCT_VHOST_VRING_ADDR */
+
+# ifdef HAVE_STRUCT_VHOST_MEMORY
+# ifdef HAVE_STRUCT_VHOST_MEMORY_REGION
+static bool
+print_vhost_memory_region(struct tcb *const tcp,
+		      void* elem_buf, size_t elem_size, void* data)
+{
+	struct vhost_memory_region region = *((struct vhost_memory_region *)elem_buf);
+
+	tprint_struct_begin();
+
+	PRINT_FIELD_X(region, guest_phys_addr);
+	tprint_struct_next();
+	PRINT_FIELD_U(region, memory_size);
+	tprint_struct_next();
+	PRINT_FIELD_X(region, userspace_addr);
+
+    // No flags currently specified
+    if (region.flags_padding != 0) {
+        tprint_struct_next();
+        PRINT_FIELD_X(region, flags_padding);
+    }
+
+	tprint_struct_end();
+
+	return true;
+}
+
+static int
+vhost_ioctl_decode_set_mem_table(struct tcb *const tcp, const unsigned int code,
+		       const kernel_ulong_t arg)
+{
+	struct vhost_memory vhost_memory_hdr;
+
+	tprint_arg_next();
+
+	if (umove_or_printaddr(tcp, arg, &vhost_memory_hdr))
+		return RVAL_IOCTL_DECODED;
+
+	tprint_struct_begin();
+
+	PRINT_FIELD_U(vhost_memory_hdr, nregions);
+	tprint_struct_next();
+
+	if (abbrev(tcp)) {
+		tprint_array_begin();
+		if (vhost_memory_hdr.nregions)
+			tprint_more_data_follows();
+		tprint_array_end();
+	} else {
+		struct vhost_memory_region region;
+		print_array(tcp, arg + sizeof(vhost_memory_hdr), vhost_memory_hdr.nregions,
+			&region, sizeof(region), tfetch_mem,
+			print_vhost_memory_region, NULL);
+	}
+
+	tprint_struct_end();
+
+	return RVAL_IOCTL_DECODED;
+}
+# endif /* HAVE_STRUCT_VHOST_MEMORY */
+# endif /* HAVE_STRUCT_VHOST_MEMORY_REGION */
+
 int
 vhost_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg)
 {
 	switch (code) {
+    # ifdef HAVE_STRUCT_VHOST_VRING_FILE
+    case VHOST_SET_VRING_KICK:
+    case VHOST_SET_VRING_CALL:
+    case VHOST_SET_VRING_ERR:
+    case VHOST_NET_SET_BACKEND:
+        return vhost_ioctl_decode_vring_file(tcp, code, arg);
+    # endif
+    # ifdef HAVE_STRUCT_VHOST_VRING_STATE
+    case VHOST_SET_VRING_NUM:
+    case VHOST_SET_VRING_BASE:
+    case VHOST_GET_VRING_BASE:
+    case VHOST_SET_VRING_ENDIAN:
+    case VHOST_GET_VRING_ENDIAN:
+    case VHOST_SET_VRING_BUSYLOOP_TIMEOUT:
+    case VHOST_GET_VRING_BUSYLOOP_TIMEOUT:
+    case VHOST_VDPA_SET_VRING_ENABLE:
+        return vhost_ioctl_decode_vring_state(tcp, code, arg);
+    # endif
+    # ifdef HAVE_STRUCT_VHOST_VRING_STATE
+    case VHOST_SET_VRING_ADDR:
+        return vhost_ioctl_decode_vring_set_addr(tcp, code, arg);
+    # endif
+    # ifdef HAVE_STRUCT_VHOST_MEMORY
+    # ifdef HAVE_STRUCT_VHOST_MEMORY_REGION
+    case VHOST_SET_MEM_TABLE:
+        return vhost_ioctl_decode_set_mem_table(tcp, code, arg);
+    # endif
+    # endif
 	default:
 		return RVAL_DECODED;
 	}
diff --git a/src/xlat/vhost_vring_flags.in b/src/xlat/vhost_vring_flags.in
new file mode 100644
index 000000000..2be344666
--- /dev/null
+++ b/src/xlat/vhost_vring_flags.in
@@ -0,0 +1 @@
+VHOST_VRING_F_LOG   (1<<0)
\ No newline at end of file
-- 
2.34.1



More information about the Strace-devel mailing list