]> granicus.if.org Git - strace/commitdiff
net.c: recvfrom fixes
authorDenys Vlasenko <dvlasenk@redhat.com>
Thu, 30 Jul 2015 11:29:20 +0000 (13:29 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Thu, 30 Jul 2015 11:38:32 +0000 (13:38 +0200)
This change fixes these three problems (before/after is shown):

On interrupted syscall, flags are not decoded:

    -recvfrom(3, 0x7fff0a41e306, 10, 2, 0, 0) = ? ERESTARTSYS
    +recvfrom(3, 0x7fff0a41e306, 10, MSG_PEEK, 0, 0) = ? ERESTARTSYS

If peer address is unavalable (example: anon sockets from socketpair()),
kernel returns socklen of 0, but we ignore that and show bogus sockaddr data:

    -recvfrom(3, "123456789\0", 10, MSG_PEEK, {sa_family=0x7777 /* AF_??? */, sa_data="wwwwwwwwwwwwww"}, [0]) = 10
    +recvfrom(3, "123456789\0", 10, MSG_PEEK, 0x7ffde6edf760, [0]) = 10

SYS_FUNC(recvfrom) passes address of fromlen, not fromlen, to printsock():

    -               printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
    +               printsock(tcp, tcp->u_arg[4], fromlen);

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
net.c

diff --git a/net.c b/net.c
index a4a2de54b53b5ea244abf4dbc1b3ea8a8a02134d..7412519bd3d2590bbf84cc565a01c547d6448ebe 100644 (file)
--- a/net.c
+++ b/net.c
@@ -146,7 +146,12 @@ printsock(struct tcb *tcp, long addr, int addrlen)
        } addrbuf;
        char string_addr[100];
 
-       if (addrlen < 2 || addrlen > (int) sizeof(addrbuf))
+       if (addrlen < 2) {
+               tprintf("%#lx", addr);
+               return;
+       }
+
+       if (addrlen > (int) sizeof(addrbuf))
                addrlen = sizeof(addrbuf);
 
        memset(&addrbuf, 0, sizeof(addrbuf));
@@ -807,28 +812,31 @@ SYS_FUNC(recvfrom)
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
        } else {
+               /* buf */
                if (syserror(tcp)) {
-                       tprintf("%#lx, %lu, %lu, %#lx, %#lx",
-                               tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3],
-                               tcp->u_arg[4], tcp->u_arg[5]);
-                       return 0;
+                       tprintf("%#lx", tcp->u_arg[1]);
+               } else {
+                       printstr(tcp, tcp->u_arg[1], tcp->u_rval);
                }
-               /* buf */
-               printstr(tcp, tcp->u_arg[1], tcp->u_rval);
                /* len */
                tprintf(", %lu, ", tcp->u_arg[2]);
                /* flags */
                printflags(msg_flags, tcp->u_arg[3], "MSG_???");
-               /* from address, len */
+               if (syserror(tcp)) {
+                       tprintf(", %#lx, %#lx", tcp->u_arg[4], tcp->u_arg[5]);
+                       return 0;
+               }
                tprints(", ");
                if (!tcp->u_arg[4] || !tcp->u_arg[5] ||
                    umove(tcp, tcp->u_arg[5], &fromlen) < 0) {
+                       /* from address, len */
                        printaddr(tcp->u_arg[4]);
                        tprints(", ");
                        printaddr(tcp->u_arg[5]);
                        return 0;
                }
-               printsock(tcp, tcp->u_arg[4], tcp->u_arg[5]);
+               /* from address */
+               printsock(tcp, tcp->u_arg[4], fromlen);
                /* from length */
                tprintf(", [%u]", fromlen);
        }