On Mon, Mar 27, 2017 at 07:25:48PM +0700, Nikolay Marchuk wrote: > * configure.ac: Add check for linux/nsfs.h header.
The tradition is to write it this way: * configure.ac (AC_CHECK_HEADERS): Add linux/nsfs.h. > * defs.h: Add definition for new ioctl decoder. * defs.h (DECL_IOCTL(nsfs)): New prototype. > * ioctl.c: Modify to support new ioctl decoder. * ioctl.c (ioctl_decode): Call nsfs_ioctl for 0xb7 code. > * 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 Trailing dot is missing. > * tests/ioctl_nsfs.c: New file. This should go before tests/.gitignore and tests/Makefile.am. > * tests/ioctl_nsfs.h: Likewise. What is tests/ioctl_nsfs.h? Where is tests/ioctl_nsfs.test? > --- > 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 \ Please keep the list sorted. > 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.nikola...@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; Please move this variable into the case. > + 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; Why 0? I though it should rather be RVAL_DECODED. > + } > +} > 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.nikola...@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]); > +} The proper pipe synchronization is implemented this way: - parent creates a pipe - parent forks a child - parent closes the read end of the pipe - child closes the write end of the pipe - child blocks in a read from the pipe - parent goes to perform other tasks - parent closes the write end of the pipe - child reads EOF from the pipe and exits - parent waits for the child You can find several examples in the test suite. -- ldv
signature.asc
Description: PGP signature
------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel