]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CVE-2016-7993/Clean up relative time stamp printing.
authorGuy Harris <[email protected]>
Sat, 8 Aug 2015 19:53:36 +0000 (12:53 -0700)
committerFrancois-Xavier Le Bail <[email protected]>
Wed, 18 Jan 2017 08:16:38 +0000 (09:16 +0100)
Have separate routines for signed and unsigned relative time stamps.
Have the routine for signed time stamps handle the case of -2^31, where
you can't negate it and have the result fit in a 32-bit signed integer.

There are currently no users of the signed relative time stamp routine,
but it's there in case anybody needs it (and is passing 32-bit
quantitites, so that there's a risk that a packet might contain -2^31 as
the time stamp).

Fixes an array overflow found with American Fuzzy Lop by Hanno Böck.

netdissect.h
print-domain.c
print-dvmrp.c
print-hsrp.c
print-igmp.c
print-lwres.c
print-pim.c
util-print.c

index b04de0060de778fab3c42d9bc88f7bf8a3e6ec48..ed1a684239277cbe4f966a2a7d861876b0c33bfb 100644 (file)
@@ -328,7 +328,8 @@ struct netdissect_options {
 #define ND_DEFAULTPRINT(ap, length) (*ndo->ndo_default_print)(ndo, ap, length)
 
 extern void ts_print(netdissect_options *, const struct timeval *);
-extern void relts_print(netdissect_options *, int);
+extern void signed_relts_print(netdissect_options *, int32_t);
+extern void unsigned_relts_print(netdissect_options *, uint32_t);
 
 extern void fn_print_char(netdissect_options *, u_char);
 extern int fn_print(netdissect_options *, const u_char *, const u_char *);
index 44d1bc828533372ccf447d5d9582f0ec5d06e323..d0b6996fda2f047ed451e76a23b91467153e49aa 100644 (file)
@@ -397,7 +397,7 @@ ns_rprint(netdissect_options *ndo,
        } else if (ndo->ndo_vflag > 2) {
                /* print ttl */
                ND_PRINT((ndo, " ["));
-               relts_print(ndo, EXTRACT_32BITS(cp));
+               unsigned_relts_print(ndo, EXTRACT_32BITS(cp));
                ND_PRINT((ndo, "]"));
                cp += 4;
        } else {
index a2527b1823c6027851f1a18aac9d769df07c1b59..60f836e8ea1d6f5a057f342729bc77a769ba8cb3 100644 (file)
@@ -338,7 +338,7 @@ print_prune(netdissect_options *ndo,
        ND_PRINT((ndo, " src %s grp %s", ipaddr_string(ndo, bp), ipaddr_string(ndo, bp + 4)));
        bp += 8;
        ND_PRINT((ndo, " timer "));
-       relts_print(ndo, EXTRACT_32BITS(bp));
+       unsigned_relts_print(ndo, EXTRACT_32BITS(bp));
        return (0);
 trunc:
        return (-1);
index af59a9d1258081de73da6301db37d96b3819b90f..35146460c8552d06344069b03a354c3f1f54c9be 100644 (file)
@@ -117,9 +117,9 @@ hsrp_print(netdissect_options *ndo, register const uint8_t *bp, register u_int l
        ND_PRINT((ndo, "addr=%s", ipaddr_string(ndo, &hp->hsrp_virtaddr)));
        if (ndo->ndo_vflag) {
                ND_PRINT((ndo, " hellotime="));
-               relts_print(ndo, hp->hsrp_hellotime);
+               unsigned_relts_print(ndo, hp->hsrp_hellotime);
                ND_PRINT((ndo, " holdtime="));
-               relts_print(ndo, hp->hsrp_holdtime);
+               unsigned_relts_print(ndo, hp->hsrp_holdtime);
                ND_PRINT((ndo, " priority=%d", hp->hsrp_priority));
                ND_PRINT((ndo, " auth=\""));
                if (fn_printn(ndo, hp->hsrp_authdata, sizeof(hp->hsrp_authdata),
index 3c6630c0e5d8dd92a9c23bfb01bd085d999ed666..9bc6025c3867fa04308b07d90d0cb6c2dbb242b6 100644 (file)
@@ -205,7 +205,7 @@ print_igmpv3_query(netdissect_options *ndo,
                    register const u_char *bp, register u_int len)
 {
     u_int mrc;
-    int mrt;
+    u_int mrt;
     u_int nsrcs;
     register u_int i;
 
@@ -227,7 +227,7 @@ print_igmpv3_query(netdissect_options *ndo,
         if (mrt < 600) {
             ND_PRINT((ndo, "%.1fs", mrt * 0.1));
         } else {
-            relts_print(ndo, mrt / 10);
+            unsigned_relts_print(ndo, mrt / 10);
         }
        ND_PRINT((ndo, "]"));
     }
index e0d83fd5f651f0e9c7a85d3d34d89089f0142d38..ae352807d006b2399e222b718eabf3dbfd24bbc2 100644 (file)
@@ -542,7 +542,7 @@ lwres_print(netdissect_options *ndo,
                                    EXTRACT_16BITS(&grbn->rdclass))));
                        }
                        ND_PRINT((ndo, " TTL "));
-                       relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
+                       unsigned_relts_print(ndo, EXTRACT_32BITS(&grbn->ttl));
                        ND_PRINT((ndo, " %u/%u", EXTRACT_16BITS(&grbn->nrdatas),
                            EXTRACT_16BITS(&grbn->nsigs)));
 
index 092c41fe196397ff2759ddb57dc5889adabd6b95..255259537494b3db0800f15b7980ede4f0aa2f74 100644 (file)
@@ -155,7 +155,7 @@ pimv1_join_prune_print(netdissect_options *ndo,
                hold = EXTRACT_16BITS(&bp[6]);
                if (hold != 180) {
                        ND_PRINT((ndo, "Hold "));
-                       relts_print(ndo, hold);
+                       unsigned_relts_print(ndo, hold);
                }
                ND_PRINT((ndo, "%s (%s/%d, %s", njoin ? "Join" : "Prune",
                ipaddr_string(ndo, &bp[26]), bp[25] & 0x3f,
@@ -177,7 +177,7 @@ pimv1_join_prune_print(netdissect_options *ndo,
        if (ndo->ndo_vflag > 1)
                ND_PRINT((ndo, "\n"));
        ND_PRINT((ndo, " Hold time: "));
-       relts_print(ndo, EXTRACT_16BITS(&bp[6]));
+       unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[6]));
        if (ndo->ndo_vflag < 2)
                return;
        bp += 8;
@@ -262,7 +262,7 @@ pimv1_print(netdissect_options *ndo,
                if (ndo->ndo_vflag) {
                        ND_TCHECK2(bp[10],2);
                        ND_PRINT((ndo, " (Hold-time "));
-                       relts_print(ndo, EXTRACT_16BITS(&bp[10]));
+                       unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[10]));
                        ND_PRINT((ndo, ")"));
                }
                break;
@@ -284,7 +284,7 @@ pimv1_print(netdissect_options *ndo,
                        if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
                                ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12])));
                        ND_PRINT((ndo, " RP %s hold ", ipaddr_string(ndo, &bp[16])));
-                       relts_print(ndo, EXTRACT_16BITS(&bp[22]));
+                       unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[22]));
                }
                break;
        case PIMV1_TYPE_ASSERT:
@@ -351,7 +351,7 @@ cisco_autorp_print(netdissect_options *ndo,
        ND_PRINT((ndo, " Hold "));
        hold = EXTRACT_16BITS(&bp[2]);
        if (hold)
-               relts_print(ndo, EXTRACT_16BITS(&bp[2]));
+               unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2]));
        else
                ND_PRINT((ndo, "FOREVER"));
 
@@ -729,7 +729,7 @@ pimv2_print(netdissect_options *ndo,
 
                        switch (otype) {
                        case PIMV2_HELLO_OPTION_HOLDTIME:
-                               relts_print(ndo, EXTRACT_16BITS(bp));
+                               unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
                                break;
 
                        case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
@@ -770,7 +770,7 @@ pimv2_print(netdissect_options *ndo,
                                ND_PRINT((ndo, "v%d", *bp));
                                if (*(bp+1) != 0) {
                                        ND_PRINT((ndo, ", interval "));
-                                       relts_print(ndo, *(bp+1));
+                                       unsigned_relts_print(ndo, *(bp+1));
                                }
                                if (EXTRACT_16BITS(bp+2) != 0) {
                                        ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2)));
@@ -932,7 +932,7 @@ pimv2_print(netdissect_options *ndo,
                        if (holdtime == 0xffff)
                                ND_PRINT((ndo, "infinite"));
                        else
-                               relts_print(ndo, holdtime);
+                               unsigned_relts_print(ndo, holdtime);
                }
                bp += 4; len -= 4;
                for (i = 0; i < ngroup; i++) {
@@ -1036,7 +1036,7 @@ pimv2_print(netdissect_options *ndo,
                                        goto bs_done;
                                }
                                ND_PRINT((ndo, ",holdtime="));
-                               relts_print(ndo, EXTRACT_16BITS(bp));
+                               unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
                                if (bp + 2 >= ep) {
                                        ND_PRINT((ndo, "...)"));
                                        goto bs_done;
@@ -1088,7 +1088,7 @@ pimv2_print(netdissect_options *ndo,
                ND_PRINT((ndo, " prio=%d", bp[1]));
                if (bp + 3 >= ep) break;
                ND_PRINT((ndo, " holdtime="));
-               relts_print(ndo, EXTRACT_16BITS(&bp[2]));
+               unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2]));
                bp += 4;
 
                /* Encoded-Unicast-RP-Address */
@@ -1134,7 +1134,7 @@ pimv2_print(netdissect_options *ndo,
                bp += advance;
                ND_TCHECK2(bp[0], 2);
                ND_PRINT((ndo, " TUNR "));
-               relts_print(ndo, EXTRACT_16BITS(bp));
+               unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
                break;
 
 
index 7071ee8a41e401e7c840eb27ad5db91b1ed02a29..0b4f055b5b3b7fbad3f2ae21daf9bfef699e6f42 100644 (file)
@@ -387,27 +387,70 @@ ts_print(netdissect_options *ndo,
 }
 
 /*
- * Print a relative number of seconds (e.g. hold time, prune timer)
+ * Print a signed relative number of seconds (e.g. hold time, prune timer)
  * in the form 5m1s.  This does no truncation, so 32230861 seconds
  * is represented as 1y1w1d1h1m1s.
  */
 void
-relts_print(netdissect_options *ndo,
-            int secs)
+signed_relts_print(netdissect_options *ndo,
+                   int32_t secs)
 {
+       uint32_t secs_abs;
        static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
-       static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
+       static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
        const char **l = lengths;
-       const int *s = seconds;
+       const u_int *s = seconds;
 
        if (secs == 0) {
                ND_PRINT((ndo, "0s"));
                return;
        }
+       if (secs == -2147483648) {
+               /*
+                * -2^31; you can't fit its absolute value into a 32-bit
+                * signed integer.
+                *
+                * We calculate the right string by hand.
+                */
+               ND_PRINT((ndo, "-68y5w3h14m8s"));
+               return;
+       }
        if (secs < 0) {
+               /*
+                * We now know -secs will fit into secs.
+                */
                ND_PRINT((ndo, "-"));
                secs = -secs;
        }
+       secs_abs = secs;
+       while (secs_abs > 0) {
+               if (secs_abs >= *s) {
+                       ND_PRINT((ndo, "%d%s", secs_abs / *s, *l));
+                       secs_abs -= (secs_abs / *s) * *s;
+               }
+               s++;
+               l++;
+       }
+}
+
+/*
+ * Print an unsigned relative number of seconds (e.g. hold time, prune timer)
+ * in the form 5m1s.  This does no truncation, so 32230861 seconds
+ * is represented as 1y1w1d1h1m1s.
+ */
+void
+unsigned_relts_print(netdissect_options *ndo,
+                     uint32_t secs)
+{
+       static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
+       static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
+       const char **l = lengths;
+       const u_int *s = seconds;
+
+       if (secs == 0) {
+               ND_PRINT((ndo, "0s"));
+               return;
+       }
        while (secs > 0) {
                if (secs >= *s) {
                        ND_PRINT((ndo, "%d%s", secs / *s, *l));