From 894c7e3858ede412e37a1752c716bed7f30a9605 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sat, 1 Feb 2014 09:57:45 -0800 Subject: [PATCH] Add decoding of sockets descriptor 'paths' for network calls * net.c (sys_bind, sys_listen, do_accept, sys_send, sys_sendto, sys_sendmsg, sys_sendmmsg, sys_recv, sys_recvfrom, sys_recvmsg, sys_recvmmsg, sys_shutdown, sys_getsockopt, sys_setsockopt): Decode socket descriptor arguments using printfd. * pathtrace.c (pathtrace_match): Also check TRACE_NETWORK syscalls that take socket descriptor arguments. * tests/net-fd.test: New test for socket descriptor arguments decoding. * tests/Makefile.am (TESTS): Add net-fd.test. (net-fd.log): New dependency on net.log. Signed-off-by: Philippe Ombredanne Signed-off-by: Dmitry V. Levin --- net.c | 43 +++++++++++++++++++++++++++++-------------- pathtrace.c | 12 +++++++----- tests/Makefile.am | 3 +++ tests/net-fd.test | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 19 deletions(-) create mode 100755 tests/net-fd.test diff --git a/net.c b/net.c index dd1e4469..b6c8cc9c 100644 --- a/net.c +++ b/net.c @@ -1711,7 +1711,8 @@ int sys_bind(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printsock(tcp, tcp->u_arg[1], tcp->u_arg[2]); tprintf(", %lu", tcp->u_arg[2]); } @@ -1728,7 +1729,9 @@ int sys_listen(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, %lu", tcp->u_arg[0], tcp->u_arg[1]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + tprintf("%lu", tcp->u_arg[1]); } return 0; } @@ -1737,7 +1740,8 @@ static int do_accept(struct tcb *tcp, int flags_arg) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); return 0; } if (!tcp->u_arg[2]) @@ -1777,7 +1781,8 @@ int sys_send(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); tprintf(", %lu, ", tcp->u_arg[2]); /* flags */ @@ -1790,7 +1795,8 @@ int sys_sendto(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); tprintf(", %lu, ", tcp->u_arg[2]); /* flags */ @@ -1810,7 +1816,8 @@ int sys_sendmsg(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printmsghdr(tcp, tcp->u_arg[1], (unsigned long) -1L); /* flags */ tprints(", "); @@ -1824,7 +1831,8 @@ sys_sendmmsg(struct tcb *tcp) { if (entering(tcp)) { /* sockfd */ - tprintf("%d, ", (int) tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); if (!verbose(tcp)) { tprintf("%#lx, %u, ", tcp->u_arg[1], (unsigned int) tcp->u_arg[2]); @@ -1843,7 +1851,8 @@ int sys_recv(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); } else { if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[1]); @@ -1862,7 +1871,8 @@ sys_recvfrom(struct tcb *tcp) int fromlen; if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); } else { if (syserror(tcp)) { tprintf("%#lx, %lu, %lu, %#lx, %#lx", @@ -1906,7 +1916,8 @@ int sys_recvmsg(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); } else { if (syserror(tcp) || !verbose(tcp)) tprintf("%#lx", tcp->u_arg[1]); @@ -1926,7 +1937,8 @@ sys_recvmmsg(struct tcb *tcp) static char str[5 + TIMESPEC_TEXT_BUFSIZE]; if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); if (verbose(tcp)) { sprint_timespec(str, tcp, tcp->u_arg[4]); /* Abusing tcp->auxstr as temp storage. @@ -1976,7 +1988,8 @@ int sys_shutdown(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printxval(shutdown_modes, tcp->u_arg[1], "SHUT_???"); } return 0; @@ -2077,7 +2090,8 @@ int sys_getsockopt(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printxval(socketlayers, tcp->u_arg[1], "SOL_???"); tprints(", "); switch (tcp->u_arg[1]) { @@ -2343,7 +2357,8 @@ int sys_setsockopt(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); printsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]); tprintf(", %lu", tcp->u_arg[4]); diff --git a/pathtrace.c b/pathtrace.c index 03f6681f..f6c3b80f 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -80,7 +80,7 @@ fdmatch(struct tcb *tcp, int fd) /* * Add a path to the set we're tracing. - * Secifying NULL will delete all paths. + * Specifying NULL will delete all paths. */ static void storepath(const char *path) @@ -158,7 +158,7 @@ pathtrace_match(struct tcb *tcp) s = tcp->s_ent; - if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC))) + if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK))) return 0; /* @@ -339,11 +339,13 @@ pathtrace_match(struct tcb *tcp) s->sys_func == sys_timerfd_settime || s->sys_func == sys_timerfd_gettime || s->sys_func == sys_epoll_create || + s->sys_func == sys_socket || + s->sys_func == sys_socketpair || strcmp(s->sys_name, "fanotify_init") == 0) { /* - * These have TRACE_FILE or TRACE_DESCRIPTOR set, but they - * don't have any file descriptor or path args to test. + * These have TRACE_FILE or TRACE_DESCRIPTOR or TRACE_NETWORK set, + * but they don't have any file descriptor or path args to test. */ return 0; } @@ -356,7 +358,7 @@ pathtrace_match(struct tcb *tcp) if (s->sys_flags & TRACE_FILE) return upathmatch(tcp, tcp->u_arg[0]); - if (s->sys_flags & TRACE_DESC) + if (s->sys_flags & (TRACE_DESC | TRACE_NETWORK)) return fdmatch(tcp, tcp->u_arg[0]); return 0; diff --git a/tests/Makefile.am b/tests/Makefile.am index 56c4a067..82226df3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,10 +11,13 @@ TESTS = \ sigaction.test \ stat.test \ net.test \ + net-fd.test \ detach-sleeping.test \ detach-stopped.test \ detach-running.test +net-fd.log: net.log + TEST_LOG_COMPILER = $(srcdir)/run.sh EXTRA_DIST = init.sh run.sh sigaction.awk $(TESTS) diff --git a/tests/net-fd.test b/tests/net-fd.test new file mode 100755 index 00000000..0f6b4e2c --- /dev/null +++ b/tests/net-fd.test @@ -0,0 +1,47 @@ +#!/bin/sh + +# Check how network syscalls are traced when decoding socket descriptors + +. "${srcdir=.}/init.sh" + +# strace -y is implemented using /proc/self/fd +[ -d /proc/self/fd/ ] || + framework_skip_ '/proc/self/fd/ is not available' + +check_prog grep +check_prog rm + +rm -f $LOG.* + +./net-accept-connect || + fail_ 'net-accept-connect failed' + +# using -y to test socket descriptors 'paths' decoding +args="-tt -ff -y -o $LOG -enetwork ./net-accept-connect" +$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 -enetwork failed to trace \"$syscall\" properly" + } +} +grep_log bind '\(0, \{sa_family=AF_(LOCAL|UNIX|FILE), sun_path="local-stream"\}, 15\) += 0' +grep_log listen '\(0, 5\) += 0' +grep_log getsockname '\(0, \{sa_family=AF_(LOCAL|UNIX|FILE), sun_path="local-stream"\}, \[15\]\) += 0' +grep_log accept '\(0, \{sa_family=AF_(LOCAL|UNIX|FILE), NULL\}, \[2\]\) += 1' +grep_log connect '\(1, \{sa_family=AF_(LOCAL|UNIX|FILE), sun_path="local-stream"\}, 15\) += 0' + +exit 0 -- 2.40.0