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:
parent
772e32b67b
commit
f23b097fc5
2
net.c
2
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("}}");
|
||||
|
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
net-accept-connect
|
||||
scm_rights
|
||||
set_ptracer_any
|
||||
sigaction
|
||||
uio
|
||||
*.log
|
||||
*.log.*
|
||||
*.o
|
||||
|
@ -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
43
tests/scm_rights-fd.test
Executable 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
70
tests/scm_rights.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user