RFC userfaultfd ioctl decode

Dr. David Alan Gilbert dgilbert at redhat.com
Thu Apr 21 13:04:33 UTC 2016


Hi,
   Please find below a decoder for the UFFDIO_COPY ioctl
on the userfaultfd fd;  but there are a few other ioctls
in the set to decode and I thought I'd ask before doing those:

  1) Is it basically on the right lines;  I'm not that confident
     I understand the return flags on the ioctl decoder function.

  2) Are there any hooks for decoding data read off an fd?  The userfaultfd
     returns structures giving address of the fault etc.

Dave


From a0f7d0e63a6d33a98d336b588830cd2dada649fc Mon Sep 17 00:00:00 2001
From: "Dr. David Alan Gilbert" <dgilbert at redhat.com>
Date: Thu, 21 Apr 2016 13:49:40 +0100
Subject: [PATCH] Decode UFFDIO_COPY ioctl

UFFDIO_COPY is one of the ioctls on the fd returned by userfaultfd.
Note that it reads from and also returns a result in it's data
structure.

* configure.ac: Add test for userfaultfd.h.
* userfaultfd.c: Add ioctl decoder.
* defs.h: declare that decoder.
* ioctl.c: Wire in the new decoder.
---
 configure.ac  |  3 +++
 defs.h        |  1 +
 ioctl.c       |  2 ++
 userfaultfd.c | 41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 47 insertions(+)

diff --git a/configure.ac b/configure.ac
index 2b29c94..cb9b494 100644
--- a/configure.ac
+++ b/configure.ac
@@ -420,6 +420,9 @@ AC_CHECK_HEADERS([linux/input.h], [
 	AC_CHECK_MEMBERS([struct input_absinfo.resolution],,, [#include <linux/input.h>])
 ])
 
+AC_CHECK_HEADERS([linux/userfaultfd.h], [
+])
+
 AC_CHECK_HEADERS([linux/bpf.h], [
 	AC_CACHE_CHECK([whether union bpf_attr.log_buf initialization works],
 		       [st_cv_have_union_bpf_attr_log_buf],
diff --git a/defs.h b/defs.h
index ac59349..4894fdb 100644
--- a/defs.h
+++ b/defs.h
@@ -649,6 +649,7 @@ extern int scsi_ioctl(struct tcb *, const unsigned int, long);
 extern int sock_ioctl(struct tcb *, const unsigned int, long);
 extern int term_ioctl(struct tcb *, const unsigned int, long);
 extern int ubi_ioctl(struct tcb *, const unsigned int, long);
+extern int uffdio_ioctl(struct tcb *, const unsigned int, long);
 extern int v4l2_ioctl(struct tcb *, const unsigned int, long);
 
 extern int tv_nz(const struct timeval *);
diff --git a/ioctl.c b/ioctl.c
index f70dc44..464329b 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -263,6 +263,8 @@ ioctl_decode(struct tcb *tcp)
 	case 'E':
 		return evdev_ioctl(tcp, code, arg);
 #endif
+	case 0xaa:
+		return uffdio_ioctl(tcp, code, arg);
 	default:
 		break;
 	}
diff --git a/userfaultfd.c b/userfaultfd.c
index 15f825a..2a06e1f 100644
--- a/userfaultfd.c
+++ b/userfaultfd.c
@@ -27,9 +27,50 @@
 
 #include "defs.h"
 #include <fcntl.h>
+#include <linux/ioctl.h>
+#ifdef HAVE_LINUX_USERFAULTFD_H
+#include <linux/userfaultfd.h>
+#endif
 
 #include "xlat/uffd_flags.h"
 
+
+int
+uffdio_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
+{
+#ifdef HAVE_LINUX_USERFAULTFD_H
+	static char auxbuf[64];
+#endif
+
+	switch (code) {
+#ifdef HAVE_LINUX_USERFAULTFD_H
+	case UFFDIO_COPY: {
+		struct uffdio_copy uc;
+		if (!umove_or_printaddr(tcp, arg, &uc)) {
+			if (entering(tcp)) {
+				tprintf("{dst=%" PRIx64 ", src=%" PRIx64
+				", len=%" PRIu64 ", mode=%" PRIu64 "}",
+				(uint64_t)uc.dst, (uint64_t)uc.src,
+				(uint64_t)uc.len, (uint64_t)uc.mode);
+				return 1;
+			} else {
+				/* copy also returns the number of bytes
+				 * copied */
+				sprintf(auxbuf, "copy=%" PRId64,
+				(int64_t)uc.copy);
+				tcp->auxstr = auxbuf;
+				return RVAL_STR | 1;
+			}
+		}
+		break;
+	}
+#endif
+
+	default:
+		return 0;
+	}
+}
+
 SYS_FUNC(userfaultfd)
 {
 	printflags(uffd_flags, tcp->u_arg[0], "UFFD_???");
-- 
2.5.5

--
Dr. David Alan Gilbert / dgilbert at redhat.com / Manchester, UK




More information about the Strace-devel mailing list