]> granicus.if.org Git - strace/commitdiff
Fix recvmsg decode: do not show more data than actually returned
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 28 Apr 2012 12:26:18 +0000 (14:26 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 28 Apr 2012 12:26:18 +0000 (14:26 +0200)
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 <vda.linux@googlemail.com>
defs.h
io.c
net.c

diff --git a/defs.h b/defs.h
index 541e163560e127edc5b2a156dcdc5b82bf4f5a90..62f35b40fc627a3428dc4e0fa76edc1e4cb5271c 100644 (file)
--- 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 5e697eca9d512d4954c68159e5f84dc239531dcb..bf5baa2968ed9b97b321e5370903932a7e3e6108 100644 (file)
--- a/io.c
+++ b/io.c
@@ -30,6 +30,7 @@
 
 #include "defs.h"
 #include <fcntl.h>
+#include <limits.h>
 #if HAVE_SYS_UIO_H
 # include <sys/uio.h>
 #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 c7f0b9709012e23142f4c32c897eb5ddc7397c24..fba521be564ee65e4e0ffbdedde0bfa94f782688 100644 (file)
--- a/net.c
+++ b/net.c
@@ -29,6 +29,7 @@
  */
 
 #include "defs.h"
+#include <limits.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -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_???");