]> granicus.if.org Git - strace/commitdiff
Fix decoding of getsockname, getpeername, accept, and accept4 syscalls
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 9 Jul 2016 21:52:43 +0000 (21:52 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 12 Jul 2016 07:39:26 +0000 (07:39 +0000)
* net.c (fetch_socklen): New function.
(decode_sockname): Use it.  On entering syscall, decode early
and return RVAL_DECODED when possible.  On error, print the address
length passed to the kernel.  Do not print more bytes of the socket
address than actually returned by the kernel.

net.c

diff --git a/net.c b/net.c
index 03922f61a9880f7907693d46a6993d2436c14522..86d93fc23c0fd6c31fa6b2845a339ede3569607a 100644 (file)
--- a/net.c
+++ b/net.c
@@ -189,24 +189,43 @@ SYS_FUNC(listen)
        return RVAL_DECODED;
 }
 
+static bool
+fetch_socklen(struct tcb *tcp, int *plen,
+             const unsigned long sockaddr, const unsigned long socklen)
+{
+       return verbose(tcp) && sockaddr && socklen
+              && umove(tcp, socklen, plen) == 0;
+}
+
 static int
 decode_sockname(struct tcb *tcp)
 {
+       int ulen, rlen;
+
        if (entering(tcp)) {
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
-               return 0;
+               if (fetch_socklen(tcp, &ulen, tcp->u_arg[1], tcp->u_arg[2])) {
+                       /* abuse of auxstr to retain state */
+                       tcp->auxstr = (void *) (long) ulen;
+                       return 0;
+               } else {
+                       printaddr(tcp->u_arg[1]);
+                       tprints(", ");
+                       printaddr(tcp->u_arg[2]);
+                       return RVAL_DECODED;
+               }
        }
 
-       int len;
-       if (!tcp->u_arg[2] || !verbose(tcp) || syserror(tcp) ||
-           umove(tcp, tcp->u_arg[2], &len) < 0) {
+       ulen = (long) tcp->auxstr;
+       tcp->auxstr = NULL;
+
+       if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &rlen) < 0) {
                printaddr(tcp->u_arg[1]);
-               tprints(", ");
-               printaddr(tcp->u_arg[2]);
+               tprintf(", [%d]", ulen);
        } else {
-               decode_sockaddr(tcp, tcp->u_arg[1], len);
-               tprintf(", [%d]", len);
+               decode_sockaddr(tcp, tcp->u_arg[1], ulen > rlen ? rlen : ulen);
+               tprintf(", [%d]", rlen);
        }
 
        return RVAL_DECODED;