[PATCH] Implement decoding of NS_* ioctl commands
Nikolay Marchuk
marchuk.nikolay.a at gmail.com
Mon Mar 27 12:25:48 UTC 2017
* configure.ac: Add check for linux/nsfs.h header.
* defs.h: Add definition for new ioctl decoder.
* ioctl.c: Modify to support new ioctl decoder.
* nsfs.c: New file.
* nsfs.h: Likewise.
* Makefile.am (strace_SOURCES): Add them.
* tests/.gitignore: Add ioctl_nsfs.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(DECODER_TESTS): Add ioctl_nsfs.test
* tests/ioctl_nsfs.c: New file.
* tests/ioctl_nsfs.h: Likewise.
---
Makefile.am | 2 +
configure.ac | 1 +
defs.h | 1 +
ioctl.c | 2 +
nsfs.c | 68 +++++++++++++++++++++++++
nsfs.h | 19 +++++++
tests/.gitignore | 1 +
tests/Makefile.am | 2 +
tests/ioctl_nsfs.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++
tests/ioctl_nsfs.test | 13 +++++
10 files changed, 243 insertions(+)
create mode 100644 nsfs.c
create mode 100644 nsfs.h
create mode 100644 tests/ioctl_nsfs.c
create mode 100755 tests/ioctl_nsfs.test
diff --git a/Makefile.am b/Makefile.am
index 8af709b..24e94ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -172,6 +172,8 @@ strace_SOURCES = \
net.c \
netlink.c \
nsig.h \
+ nsfs.h \
+ nsfs.c \
numa.c \
oldstat.c \
open.c \
diff --git a/configure.ac b/configure.ac
index 9e5087b..dc49fdc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -366,6 +366,7 @@ AC_CHECK_HEADERS(m4_normalize([
linux/ipc.h
linux/mmtimer.h
linux/msg.h
+ linux/nsfs.h
linux/perf_event.h
linux/quota.h
linux/seccomp.h
diff --git a/defs.h b/defs.h
index 793971e..0f3ec14 100644
--- a/defs.h
+++ b/defs.h
@@ -640,6 +640,7 @@ name ## _ioctl(struct tcb *, unsigned int request, kernel_ulong_t arg)
DECL_IOCTL(dm);
DECL_IOCTL(file);
DECL_IOCTL(fs_x);
+DECL_IOCTL(nsfs);
DECL_IOCTL(ptp);
DECL_IOCTL(scsi);
DECL_IOCTL(term);
diff --git a/ioctl.c b/ioctl.c
index aa1880f..4511e0b 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -280,6 +280,8 @@ ioctl_decode(struct tcb *tcp)
case 0x94:
return btrfs_ioctl(tcp, code, arg);
#endif
+ case 0xb7:
+ return nsfs_ioctl(tcp, code, arg);
#ifdef HAVE_LINUX_DM_IOCTL_H
case 0xfd:
return dm_ioctl(tcp, code, arg);
diff --git a/nsfs.c b/nsfs.c
new file mode 100644
index 0000000..28abcb8
--- /dev/null
+++ b/nsfs.c
@@ -0,0 +1,68 @@
+/*
+ * Support for decoding of NS_* ioctl commands.
+ *
+ * Copyright (c) 2017 Nikolay Marchuk <marchuk.nikolay.a at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+
+#include <linux/ioctl.h>
+#include "nsfs.h"
+#include "xlat/setns_types.h"
+
+int
+nsfs_ioctl(struct tcb *tcp, unsigned int code, kernel_ulong_t arg)
+{
+ const char *outstr;
+ uid_t uid;
+ switch (code) {
+ case NS_GET_USERNS:
+ case NS_GET_PARENT:
+ return 1 + RVAL_FD + RVAL_DECODED;
+ case NS_GET_NSTYPE:
+ if (entering(tcp))
+ return 0;
+ if (!syserror(tcp)) {
+ outstr = xlookup(setns_types, tcp->u_rval);
+ if (outstr) {
+ tcp->auxstr = outstr;
+ return 1 + RVAL_STR;
+ }
+ }
+ return 1;
+ case NS_GET_OWNER_UID:
+ if (entering(tcp))
+ return 0;
+ tprints(", ");
+ if (!umove_or_printaddr(tcp, arg, &uid)) {
+ printuid("[", uid);
+ tprints("]");
+ }
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/nsfs.h b/nsfs.h
new file mode 100644
index 0000000..d3a6fca
--- /dev/null
+++ b/nsfs.h
@@ -0,0 +1,19 @@
+#ifndef STRACE_NSFS_H
+#define STRACE_NSFS_H
+
+#ifdef HAVE_LINUX_NSFS_H
+# include <linux/nsfs.h>
+#else
+# define NSIO 0xb7
+# define NS_GET_USERNS _IO(NSIO, 0x1)
+# define NS_GET_PARENT _IO(NSIO, 0x2)
+#endif
+
+#ifndef NS_GET_NSTYPE
+# define NS_GET_NSTYPE _IO(NSIO, 0x3)
+#endif
+#ifndef NS_GET_OWNER_UID
+# define NS_GET_OWNER_UID _IO(NSIO, 0x4)
+#endif
+
+#endif /* !STRACE_NSFS_H */
diff --git a/tests/.gitignore b/tests/.gitignore
index 477529d..1998097 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -122,6 +122,7 @@ ioctl_loop
ioctl_loop-nv
ioctl_loop-v
ioctl_mtd
+ioctl_nsfs
ioctl_rtc
ioctl_rtc-v
ioctl_scsi
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c6c28cc..44b0463 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -185,6 +185,7 @@ check_PROGRAMS = \
ioctl_loop-nv \
ioctl_loop-v \
ioctl_mtd \
+ ioctl_nsfs \
ioctl_rtc \
ioctl_rtc-v \
ioctl_scsi \
@@ -595,6 +596,7 @@ DECODER_TESTS = \
ioctl_loop-v.test \
ioctl_loop.test \
ioctl_mtd.test \
+ ioctl_nsfs.test \
ioctl_rtc-v.test \
ioctl_rtc.test \
ioctl_scsi.test \
diff --git a/tests/ioctl_nsfs.c b/tests/ioctl_nsfs.c
new file mode 100644
index 0000000..58364d7
--- /dev/null
+++ b/tests/ioctl_nsfs.c
@@ -0,0 +1,134 @@
+/*
+ * Check decoding of NS_* commands of ioctl syscall.
+ *
+ * Copyright (c) 2017 Nikolay Marchuk <marchuk.nikolay.a at gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+
+#include <fcntl.h>
+#include <linux/ioctl.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include "nsfs.h"
+
+static void
+test_no_namespace(void)
+{
+ ioctl(-1, NS_GET_USERNS);
+ printf("ioctl(-1, NS_GET_USERNS) = -1 EBADF (%m)\n");
+ ioctl(-1, NS_GET_PARENT);
+ printf("ioctl(-1, NS_GET_PARENT) = -1 EBADF (%m)\n");
+ ioctl(-1, NS_GET_NSTYPE);
+ printf("ioctl(-1, NS_GET_NSTYPE) = -1 EBADF (%m)\n");
+ ioctl(-1, NS_GET_OWNER_UID, NULL);
+ printf("ioctl(-1, NS_GET_OWNER_UID, NULL) = -1 EBADF (%m)\n");
+}
+
+static void
+test_clone(pid_t pid)
+{
+ int ns_fd, userns_fd, parent_ns_fd, nstype, rc;
+ /* Path length with terminator is less then 22 in any case. */
+ char path[22];
+ TAIL_ALLOC_OBJECT_CONST_PTR(uid_t, uid);
+
+ snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
+ ns_fd = open(path, O_RDONLY);
+ if (ns_fd == -1)
+ perror_msg_and_skip("open: %s", path);
+
+ userns_fd = ioctl(ns_fd, NS_GET_USERNS);
+ printf("ioctl(%d, NS_GET_USERNS) = %s\n", ns_fd, sprintrc(userns_fd));
+
+ parent_ns_fd = ioctl(userns_fd, NS_GET_PARENT);
+ printf("ioctl(%d, NS_GET_PARENT) = %s\n", userns_fd,
+ sprintrc(parent_ns_fd));
+
+ nstype = ioctl(userns_fd, NS_GET_NSTYPE);
+ if (nstype == -1) {
+ printf("ioctl(%d, NS_GET_NSTYPE) = %s\n", userns_fd, sprintrc(nstype));
+ } else {
+ printf("ioctl(%d, NS_GET_NSTYPE) = %d (CLONE_NEWUSER)\n", userns_fd,
+ nstype);
+ }
+
+ rc = ioctl(userns_fd, NS_GET_OWNER_UID, uid);
+ if (rc == -1) {
+ printf("ioctl(%d, NS_GET_OWNER_UID, %p) = %s\n", userns_fd, uid,
+ sprintrc(rc));
+ } else {
+ printf("ioctl(%d, NS_GET_OWNER_UID, [%u]) = %d\n", userns_fd, *uid, rc);
+ }
+}
+
+static int
+child(void *arg)
+{
+ char c;
+ int *pipefd = (int *)arg;
+ while (read(pipefd[1], &c, 1) != 1);
+ close(pipefd[1]);
+ return 0;
+}
+
+#define STACK_SIZE (1024 * 1024)
+
+static void
+test_user_namespace(void)
+{
+ char stack[STACK_SIZE];
+ pid_t pid;
+ int pipefd[2];
+ int rc;
+
+ rc = pipe(pipefd);
+ if (rc == -1)
+ perror_msg_and_skip("pipe");
+
+ pid = clone(child, stack + STACK_SIZE, CLONE_NEWUSER | CLONE_UNTRACED,
+ pipefd);
+ if (pid == -1)
+ perror_msg_and_skip("clone");
+
+ test_clone(pid);
+ if (write(pipefd[0], "", 1) != 1){
+ perror_msg_and_skip("pipe write");
+ }
+ close(pipefd[0]);
+}
+
+int
+main(void)
+{
+ test_no_namespace();
+ test_user_namespace();
+ puts("+++ exited with 0 +++");
+ return 0;
+}
diff --git a/tests/ioctl_nsfs.test b/tests/ioctl_nsfs.test
new file mode 100755
index 0000000..8fe8da5
--- /dev/null
+++ b/tests/ioctl_nsfs.test
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Check decoding of NS_* ioctls.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+run_strace -a16 -eioctl $args > "$EXP"
+check_prog grep
+grep -v '^ioctl([012],' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
+
+rm -f "$EXP" "$OUT"
--
2.1.4
More information about the Strace-devel
mailing list