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.
This commit is contained in:
Дмитрий Левин 2014-05-29 21:35:34 +00:00
parent 772e32b67b
commit f23b097fc5
5 changed files with 123 additions and 2 deletions

2
net.c
View File

@ -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("}}");

2
tests/.gitignore vendored
View File

@ -1,6 +1,8 @@
net-accept-connect
scm_rights
set_ptracer_any
sigaction
uio
*.log
*.log.*
*.o

View File

@ -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 \

43
tests/scm_rights-fd.test Executable file
View File

@ -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<socket:\[[0-9]+\]>, \{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</dev/null>\}\}, msg_flags=0\}, 0\) += [1-9][0-9]*'
grep_log recvmsg '\(0<socket:\[[0-9]+\]>, \{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</dev/null>\}\}, msg_flags=0\}, 0\) += [1-9][0-9]*'
exit 0

70
tests/scm_rights.c Normal file
View File

@ -0,0 +1,70 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/wait.h>
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;
}