]> granicus.if.org Git - strace/commitdiff
net: accept arbitrary option length for getsockopt's SO_PEERCRED
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 8 Jul 2017 19:27:26 +0000 (19:27 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 8 Jul 2017 19:27:26 +0000 (19:27 +0000)
* print_fields.h (PRINT_FIELD_UID): New macro.
* net.c (print_ucred): Rewrite to match the kernel behaviour.
* NEWS: Mention this.

NEWS
net.c
print_fields.h

diff --git a/NEWS b/NEWS
index 947d506c0eb3ccab6b935d64bfc28d73af08dd06..50ca640a9026044416a5587ac007db7139b70e6b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,8 @@ Noteworthy changes in release ?.?? (????-??-??)
 
 * Improvements
   * Enhanced decoding of optlen argument of getsockopt syscall.
-  * Enhanced decoding of SO_LINGER option of getsockopt and setsockopt syscalls.
+  * Enhanced decoding of SO_LINGER and SO_PEERCRED options
+    of getsockopt and setsockopt syscalls.
   * Implemented decoding of linux socket filter programs specified
     for SO_ATTACH_FILTER and SO_ATTACH_REUSEPORT_CBPF socket options.
 
diff --git a/net.c b/net.c
index 257e0df3fc174868119ae0a02dede1b9254221ba..01f53b682f3b047d6264f0367e0901c65cc18d89 100644 (file)
--- a/net.c
+++ b/net.c
@@ -533,19 +533,31 @@ print_get_linger(struct tcb *const tcp, const kernel_ulong_t addr,
 
 #ifdef SO_PEERCRED
 static void
-print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
+print_ucred(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int len)
 {
        struct ucred uc;
 
-       if (len != sizeof(uc) ||
-           umove(tcp, addr, &uc) < 0) {
-               printaddr(addr);
+       if (len < sizeof(uc)) {
+               if (len != sizeof(uc.pid)
+                   && len != offsetofend(struct ucred, uid)) {
+                       printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
+                       return;
+               }
        } else {
-               tprintf("{pid=%u, uid=%u, gid=%u}",
-                       (unsigned) uc.pid,
-                       (unsigned) uc.uid,
-                       (unsigned) uc.gid);
+               len = sizeof(uc);
+       }
+
+       if (umoven(tcp, addr, len, &uc) < 0) {
+               printaddr(addr);
+               return;
        }
+
+       PRINT_FIELD_D("{", uc, pid);
+       if (len > sizeof(uc.pid))
+               PRINT_FIELD_UID(", ", uc, uid);
+       if (len == sizeof(uc))
+               PRINT_FIELD_UID(", ", uc, gid);
+       tprints("}");
 }
 #endif /* SO_PEERCRED */
 
index 92b8a8a118bb87fe44001ab6b799beac042cae77..43a26bc77ba44c7e135a32bab09399c4786a03e6 100644 (file)
                printxval((xlat_), (where_).field_, (dflt_));           \
        } while (0)
 
+#define PRINT_FIELD_UID(prefix_, where_, field_)                                       \
+       do {                                                                            \
+               if (sign_extend_unsigned_to_ll((where_).field_) == -1LL)                \
+                       STRACE_PRINTF("%s%s=-1", (prefix_), #field_);                   \
+               else                                                                    \
+                       STRACE_PRINTF("%s%s=%llu", (prefix_), #field_,                  \
+                                     zero_extend_signed_to_ull((where_).field_));      \
+       } while (0)
+
 #endif /* !STRACE_PRINT_FIELDS_H */