From: Dmitry V. Levin Date: Thu, 29 May 2014 21:35:34 +0000 (+0000) Subject: Decode file descriptors passed via SCM_RIGHTS control messages X-Git-Tag: v4.9~73 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f23b097fc5fdc031dc795c10876d97f31b2826d8;p=strace Decode file descriptors passed via SCM_RIGHTS control messages * net.c (printcmsghdr): Print descriptors from SCM_RIGHTS control messages using printfd. * tests/scm_rights.c: New file. * tests/scm_rights-fd.test: New test. * tests/Makefile.am (check_PROGRAMS): Add scm_rights. (TESTS): Add scm_rights-fd.test. * tests/.gitignore: Add scm_rights and uio. --- diff --git a/net.c b/net.c index a466efe0..e0b225e2 100644 --- a/net.c +++ b/net.c @@ -1574,7 +1574,7 @@ printcmsghdr(struct tcb *tcp, unsigned long addr, unsigned long len) while ((char *) fds < ((char *) cmsg + cmsg_len)) { if (!first) tprints(", "); - tprintf("%d", *fds++); + printfd(tcp, *fds++); first = 0; } tprints("}}"); diff --git a/tests/.gitignore b/tests/.gitignore index c400a79b..7a87842d 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,6 +1,8 @@ net-accept-connect +scm_rights set_ptracer_any sigaction +uio *.log *.log.* *.o diff --git a/tests/Makefile.am b/tests/Makefile.am index e65312c2..b561ce3e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,7 +2,12 @@ AM_CFLAGS = $(WARN_CFLAGS) -check_PROGRAMS = net-accept-connect set_ptracer_any sigaction uio +check_PROGRAMS = \ + net-accept-connect \ + scm_rights \ + set_ptracer_any \ + sigaction \ + uio uio_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64 @@ -10,6 +15,7 @@ TESTS = \ ptrace_setoptions.test \ strace-f.test \ qual_syscall.test \ + scm_rights-fd.test \ sigaction.test \ stat.test \ net.test \ diff --git a/tests/scm_rights-fd.test b/tests/scm_rights-fd.test new file mode 100755 index 00000000..e0b8f4a7 --- /dev/null +++ b/tests/scm_rights-fd.test @@ -0,0 +1,43 @@ +#!/bin/sh + +# Check how SCM_RIGHTS control messages are decoded in -y mode. + +. "${srcdir=.}/init.sh" + +# strace -y is implemented using /proc/$pid/fd +[ -d /proc/self/fd/ ] || + framework_skip_ '/proc/self/fd/ is not available' + +check_prog grep +check_prog rm + +rm -f $LOG.* + +./scm_rights || + fail_ 'scm_rights failed' + +args="-tt -ff -y -xx -enetwork -o $LOG ./scm_rights" +$STRACE $args || + fail_ "$STRACE $args failed" + +"$srcdir"/../strace-log-merge $LOG > $LOG || { + cat $LOG + fail_ 'strace-log-merge failed' +} +rm -f $LOG.* + +grep_log() +{ + local syscall="$1"; shift + local prefix='[1-9][0-9]* +[0-9]+:[0-9]+:[0-9]+\.[0-9]+ +' + + LC_ALL=C grep -E -x "$prefix$syscall$*" $LOG > /dev/null || { + cat $LOG + fail_ "$STRACE $args failed to trace \"$syscall\" properly" + } +} + +grep_log sendmsg '\(1, \{msg_name\(0\)=NULL, msg_iov\(1\)=\[\{"\\x03\\x00\\x00\\x00[^"]*", [1-9][0-9]*\}\], msg_controllen=[1-9][0-9]*, \{cmsg_len=[1-9][0-9]*, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, \{3\}\}, msg_flags=0\}, 0\) += [1-9][0-9]*' +grep_log recvmsg '\(0, \{msg_name\(0\)=NULL, msg_iov\(1\)=\[\{"\\x03\\x00\\x00\\x00[^"]*", [1-9][0-9]*\}\], msg_controllen=[1-9][0-9]*, \{cmsg_len=[1-9][0-9]*, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, \{3\}\}, msg_flags=0\}, 0\) += [1-9][0-9]*' + +exit 0 diff --git a/tests/scm_rights.c b/tests/scm_rights.c new file mode 100644 index 00000000..9522ba14 --- /dev/null +++ b/tests/scm_rights.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int main(void) +{ + union { + struct cmsghdr cmsghdr; + char buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + + int fd; + struct iovec iov = { + .iov_base = &fd, + .iov_len = sizeof(iov) + }; + + struct msghdr mh = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control) + }; + + while ((fd = open("/dev/null", O_RDWR)) < 3) + assert(fd >= 0); + (void) close(3); + + int sv[2]; + assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); + + pid_t pid = fork(); + assert(pid >= 0); + + if (pid) { + assert(close(sv[0]) == 0); + assert(dup2(sv[1], 1) == 1); + assert(close(sv[1]) == 0); + + assert((fd = open("/dev/null", O_RDWR)) == 3); + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof fd); + memcpy(CMSG_DATA(cmsg), &fd, sizeof fd); + mh.msg_controllen = cmsg->cmsg_len; + + assert(sendmsg(1, &mh, 0) == sizeof(iov)); + assert(close(1) == 0); + + int status; + assert(waitpid(pid, &status, 0) == pid); + assert(status == 0); + } else { + assert(close(sv[1]) == 0); + assert(dup2(sv[0], 0) == 0); + assert(close(sv[0]) == 0); + + assert(recvmsg(0, &mh, 0) == sizeof(iov)); + assert(close(0) == 0); + } + + return 0; +}