From e0bc222263cf47a43e1b26d55edb2ffadc8ccbff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 28 Apr 2012 14:26:18 +0200 Subject: [PATCH] Fix recvmsg decode: do not show more data than actually returned I noticed that "hostname -d" talks over netlink and gets 20 bytes of response, but we show entire 1024 bytes of iov. This changes fixes that. * defs.h: New function tprint_iov_upto. * io.c (tprint_iov_upto): Definition of this function. (tprint_iov): Call tprint_iov_upto. * net.c (do_msghdr): Add data_size parameter, pass it down to tprint_iov_upto. (printmsghdr): Add data_size parameter, pass it down to do_msghdr. (printmmsghdr): Call do_msghdr with data_size==ULONG_MAX. (sys_sendmsg): Call printmsghdr with data_size==ULONG_MAX. (sys_recvmsg): Call printmsghdr with data_size==tcp->u_rval. Signed-off-by: Denys Vlasenko --- defs.h | 1 + io.c | 23 +++++++++++++++++++---- net.c | 17 +++++++++-------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/defs.h b/defs.h index 541e1635..62f35b40 100644 --- a/defs.h +++ b/defs.h @@ -580,6 +580,7 @@ extern void printcall(struct tcb *); extern void print_sigset(struct tcb *, long, int); extern void printsignal(int); extern void tprint_iov(struct tcb *, unsigned long, unsigned long, int decode_iov); +extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, int decode_iov, unsigned long); extern void tprint_open_modes(mode_t); extern const char *sprint_open_modes(mode_t); extern void print_loff_t(struct tcb *, long); diff --git a/io.c b/io.c index 5e697eca..bf5baa29 100644 --- a/io.c +++ b/io.c @@ -30,6 +30,7 @@ #include "defs.h" #include +#include #if HAVE_SYS_UIO_H # include #endif @@ -63,8 +64,12 @@ sys_write(struct tcb *tcp) } #if HAVE_SYS_UIO_H +/* + * data_size limits the cumulative size of printed data. + * Example: recvmsg returing a short read. + */ void -tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov) +tprint_iov_upto(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov, unsigned long data_size) { #if SUPPORTED_PERSONALITIES > 1 union { @@ -117,9 +122,13 @@ tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_io break; } tprints("{"); - if (decode_iov) - printstr(tcp, (long) iov_iov_base, iov_iov_len); - else + if (decode_iov) { + unsigned long len = iov_iov_len; + if (len > data_size) + len = data_size; + data_size -= len; + printstr(tcp, (long) iov_iov_base, len); + } else tprintf("%#lx", (long) iov_iov_base); tprintf(", %lu}", (unsigned long)iov_iov_len); } @@ -131,6 +140,12 @@ tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_io #undef iov_iov_len } +void +tprint_iov(struct tcb *tcp, unsigned long len, unsigned long addr, int decode_iov) +{ + tprint_iov_upto(tcp, len, addr, decode_iov, ULONG_MAX); +} + int sys_readv(struct tcb *tcp) { diff --git a/net.c b/net.c index c7f0b970..fba521be 100644 --- a/net.c +++ b/net.c @@ -29,6 +29,7 @@ */ #include "defs.h" +#include #include #include #include @@ -1405,14 +1406,14 @@ printcmsghdr(struct tcb *tcp, unsigned long addr, unsigned long len) } static void -do_msghdr(struct tcb *tcp, struct msghdr *msg) +do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size) { tprintf("{msg_name(%d)=", msg->msg_namelen); printsock(tcp, (long)msg->msg_name, msg->msg_namelen); tprintf(", msg_iov(%lu)=", (unsigned long)msg->msg_iovlen); - tprint_iov(tcp, (unsigned long)msg->msg_iovlen, - (unsigned long)msg->msg_iov, 1); + tprint_iov_upto(tcp, (unsigned long)msg->msg_iovlen, + (unsigned long)msg->msg_iov, 1, data_size); #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL tprintf(", msg_controllen=%lu", (unsigned long)msg->msg_controllen); @@ -1429,7 +1430,7 @@ do_msghdr(struct tcb *tcp, struct msghdr *msg) } static void -printmsghdr(struct tcb *tcp, long addr) +printmsghdr(struct tcb *tcp, long addr, unsigned long data_size) { struct msghdr msg; @@ -1437,7 +1438,7 @@ printmsghdr(struct tcb *tcp, long addr) tprintf("%#lx", addr); return; } - do_msghdr(tcp, &msg); + do_msghdr(tcp, &msg, data_size); } static void @@ -1454,7 +1455,7 @@ printmmsghdr(struct tcb *tcp, long addr, unsigned int idx) return; } tprints("{"); - do_msghdr(tcp, &mmsg.msg_hdr); + do_msghdr(tcp, &mmsg.msg_hdr, ULONG_MAX); tprintf(", %u}", mmsg.msg_len); } @@ -1638,7 +1639,7 @@ sys_sendmsg(struct tcb *tcp) { if (entering(tcp)) { tprintf("%ld, ", tcp->u_arg[0]); - printmsghdr(tcp, tcp->u_arg[1]); + printmsghdr(tcp, tcp->u_arg[1], ULONG_MAX); /* flags */ tprints(", "); printflags(msg_flags, tcp->u_arg[2], "MSG_???"); @@ -1738,7 +1739,7 @@ sys_recvmsg(struct tcb *tcp) if (syserror(tcp) || !verbose(tcp)) tprintf("%#lx", tcp->u_arg[1]); else - printmsghdr(tcp, tcp->u_arg[1]); + printmsghdr(tcp, tcp->u_arg[1], tcp->u_rval); /* flags */ tprints(", "); printflags(msg_flags, tcp->u_arg[2], "MSG_???"); -- 2.40.0