]> granicus.if.org Git - strace/commitdiff
net: enhance decoding of getsockopt's optlen argument
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 8 Jul 2017 14:57:44 +0000 (14:57 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 8 Jul 2017 14:57:44 +0000 (14:57 +0000)
As the last argument of getsockopt syscall has read-write semantics,
print both user and kernel values when they differ.

* net.c (SYS_FUNC(getsockopt)): On entering syscall, fetch and save
the length specified to the kernel.  On error, print the length saved
on entering.  When the saved length and the length returned by the
kernel differ, print both values.
* NEWS: Mention this.
* tests/net-icmp_filter.c (main): Update expected output.

NEWS
net.c
tests/net-icmp_filter.c

diff --git a/NEWS b/NEWS
index 1e82a6078154a5dc6ac66788cf98494ccfaacab5..70f9fa2f699a954fa1cb395e1f1be0b9c9b82f40 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 Noteworthy changes in release ?.?? (????-??-??)
 ===============================================
 
+* Improvements
+  * Enhanced decoding of optlen argument of getsockopt syscall.
 
 Noteworthy changes in release 4.18 (2017-07-05)
 ===============================================
diff --git a/net.c b/net.c
index bfa794f99534f0dd20e8f8eabf930246f2b4cb38..807eb2509b35ee85fb198d86cd9e0de1c2099220 100644 (file)
--- a/net.c
+++ b/net.c
@@ -614,20 +614,35 @@ print_getsockopt(struct tcb *const tcp, const unsigned int level,
 
 SYS_FUNC(getsockopt)
 {
+       int ulen, rlen;
+
        if (entering(tcp)) {
                print_sockopt_fd_level_name(tcp, tcp->u_arg[0],
                                            tcp->u_arg[1], tcp->u_arg[2], true);
-       } else {
-               int len;
 
-               if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &len) < 0) {
+               if (verbose(tcp) && tcp->u_arg[4]
+                   && umove(tcp, tcp->u_arg[4], &ulen) == 0) {
+                       set_tcb_priv_ulong(tcp, ulen);
+                       return 0;
+               } else {
                        printaddr(tcp->u_arg[3]);
                        tprints(", ");
                        printaddr(tcp->u_arg[4]);
+                       return RVAL_DECODED;
+               }
+       } else {
+               ulen = get_tcb_priv_ulong(tcp);
+
+               if (syserror(tcp) || umove(tcp, tcp->u_arg[4], &rlen) < 0) {
+                       printaddr(tcp->u_arg[3]);
+                       tprintf(", [%d]", ulen);
                } else {
                        print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
-                                        tcp->u_arg[3], len);
-                       tprintf(", [%d]", len);
+                                        tcp->u_arg[3], rlen);
+                       if (ulen != rlen)
+                               tprintf(", [%d->%d]", ulen, rlen);
+                       else
+                               tprintf(", [%d]", rlen);
                }
        }
        return 0;
index 71e530d202f4073e165e7963e22dcbd4cfd3519c..1dd1f2182028f57ffcb03067943ae488474003af 100644 (file)
@@ -49,8 +49,8 @@ main(void)
        TAIL_ALLOC_OBJECT_CONST_PTR(struct icmp_filter, f);
 
        getsockopt(-1, SOL_RAW, ICMP_FILTER, f, plen);
-       printf("getsockopt(-1, SOL_RAW, ICMP_FILTER, %p, %p) = -1 %s (%m)\n",
-              f, plen, errno2name());
+       printf("getsockopt(-1, SOL_RAW, ICMP_FILTER, %p, [%d]) = -1 %s (%m)\n",
+              f, *plen, errno2name());
 
        setsockopt(-1, SOL_RAW, ICMP_FILTER, efault, sizeof(*f));
        printf("setsockopt(-1, SOL_RAW, ICMP_FILTER, %p, %u) = -1 %s (%m)\n",