]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Do more bounds checking and length checking.
authorGuy Harris <[email protected]>
Wed, 12 Nov 2014 00:49:39 +0000 (16:49 -0800)
committerGuy Harris <[email protected]>
Wed, 19 Nov 2014 08:22:39 +0000 (00:22 -0800)
Don't run past the end of the captured data, and don't run past the end
of the packet (i.e., don't make the length variable go negative).

Also, stop dissecting if the message length isn't valid.

print-olsr.c

index ba0ed2bede8a14569e98de85aab86a113264a3d7..733780f233e3194ac6dbe6489278ab1eb7f07c67 100644 (file)
@@ -181,7 +181,7 @@ struct olsr_lq_neighbor6 {
 /*
  * print a neighbor list with LQ extensions.
  */
-static void
+static int
 olsr_print_lq_neighbor4 (const u_char *msg_data, u_int hello_len)
 {
     struct olsr_lq_neighbor4 *lq_neighbor;
@@ -189,6 +189,8 @@ olsr_print_lq_neighbor4 (const u_char *msg_data, u_int hello_len)
     while (hello_len >= sizeof(struct olsr_lq_neighbor4)) {
 
         lq_neighbor = (struct olsr_lq_neighbor4 *)msg_data;
+        if (!TTEST(*lq_neighbor))
+            return (-1);
 
         printf("\n\t      neighbor %s, link-quality %.2lf%%"
                ", neighbor-link-quality %.2lf%%",
@@ -199,10 +201,11 @@ olsr_print_lq_neighbor4 (const u_char *msg_data, u_int hello_len)
         msg_data += sizeof(struct olsr_lq_neighbor4);
         hello_len -= sizeof(struct olsr_lq_neighbor4);
     }
+    return (0);
 }
 
 #if INET6
-static void
+static int
 olsr_print_lq_neighbor6 (const u_char *msg_data, u_int hello_len)
 {
     struct olsr_lq_neighbor6 *lq_neighbor;
@@ -210,6 +213,8 @@ olsr_print_lq_neighbor6 (const u_char *msg_data, u_int hello_len)
     while (hello_len >= sizeof(struct olsr_lq_neighbor6)) {
 
         lq_neighbor = (struct olsr_lq_neighbor6 *)msg_data;
+        if (!TTEST(*lq_neighbor))
+            return (-1);
 
         printf("\n\t      neighbor %s, link-quality %.2lf%%"
                ", neighbor-link-quality %.2lf%%",
@@ -220,13 +225,14 @@ olsr_print_lq_neighbor6 (const u_char *msg_data, u_int hello_len)
         msg_data += sizeof(struct olsr_lq_neighbor6);
         hello_len -= sizeof(struct olsr_lq_neighbor6);
     }
+    return (0);
 }
 #endif /* INET6 */
 
 /*
  * print a neighbor list.
  */
-static void
+static int
 olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
 {
     int neighbor;
@@ -236,6 +242,8 @@ olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
 
     while (hello_len >= sizeof(struct in_addr)) {
 
+        if (!TTEST2(*msg_data, sizeof(struct in_addr)))
+            return (-1);
         /* print 4 neighbors per line */
 
         printf("%s%s", ipaddr_string(msg_data),
@@ -244,6 +252,7 @@ olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
         msg_data += sizeof(struct in_addr);
         hello_len -= sizeof(struct in_addr);
     }
+    return (0);
 }
 
 
@@ -328,6 +337,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                     ME_TO_DOUBLE(msgptr.v6->vtime),
                     EXTRACT_16BITS(msgptr.v6->msg_seq),
                     msg_len, (msg_len_valid == 0) ? " (invalid)" : "");
+            if (!msg_len_valid) {
+                return;
+            }
 
             msg_tlen = msg_len - sizeof(struct olsr_msg6);
             msg_data = tptr + sizeof(struct olsr_msg6);
@@ -356,6 +368,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                     ME_TO_DOUBLE(msgptr.v4->vtime),
                     EXTRACT_16BITS(msgptr.v4->msg_seq),
                     msg_len, (msg_len_valid == 0) ? " (invalid)" : "");
+            if (!msg_len_valid) {
+                return;
+            }
 
             msg_tlen = msg_len - sizeof(struct olsr_msg4);
             msg_data = tptr + sizeof(struct olsr_msg4);
@@ -364,8 +379,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
         switch (msg_type) {
         case OLSR_HELLO_MSG:
         case OLSR_HELLO_LQ_MSG:
-            if (!TTEST2(*msg_data, sizeof(struct olsr_hello)))
+            if (msg_tlen < sizeof(struct olsr_hello))
                 goto trunc;
+            TCHECK2(*msg_data, sizeof(struct olsr_hello));
 
             ptr.hello = (struct olsr_hello *)msg_data;
             printf("\n\t  hello-time %.3lfs, MPR willingness %u",
@@ -405,15 +421,21 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
                 msg_tlen -= sizeof(struct olsr_hello_link);
                 hello_len -= sizeof(struct olsr_hello_link);
 
+                TCHECK2(*msg_data, hello_len);
                 if (msg_type == OLSR_HELLO_MSG) {
-                    olsr_print_neighbor(msg_data, hello_len);
+                    if (olsr_print_neighbor(msg_data, hello_len) == -1)
+                        goto trunc;
                 } else {
 #if INET6
-                    if (is_ipv6)
-                        olsr_print_lq_neighbor6(msg_data, hello_len);
-                    else
+                    if (is_ipv6) {
+                        if (olsr_print_lq_neighbor6(msg_data, hello_len) == -1)
+                            goto trunc;
+                    } else
 #endif
-                        olsr_print_lq_neighbor4(msg_data, hello_len);
+                    {
+                        if (olsr_print_lq_neighbor4(msg_data, hello_len) == -1)
+                            goto trunc;
+                    }
                 }
 
                 msg_data += hello_len;
@@ -423,8 +445,9 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
 
         case OLSR_TC_MSG:
         case OLSR_TC_LQ_MSG:
-            if (!TTEST2(*msg_data, sizeof(struct olsr_tc)))
+            if (msg_tlen < sizeof(struct olsr_tc))
                 goto trunc;
+            TCHECK2(*msg_data, sizeof(struct olsr_tc));
 
             ptr.tc = (struct olsr_tc *)msg_data;
             printf("\n\t    advertised neighbor seq 0x%04x",
@@ -433,14 +456,19 @@ olsr_print (const u_char *pptr, u_int length, int is_ipv6)
             msg_tlen -= sizeof(struct olsr_tc);
 
             if (msg_type == OLSR_TC_MSG) {
-                olsr_print_neighbor(msg_data, msg_tlen);
+                if (olsr_print_neighbor(msg_data, msg_tlen) == -1)
+                    goto trunc;
             } else {
 #if INET6
-                if (is_ipv6)
-                    olsr_print_lq_neighbor6(msg_data, msg_tlen);
-                else
+                if (is_ipv6) {
+                    if (olsr_print_lq_neighbor6(msg_data, msg_tlen) == -1)
+                        goto trunc;
+                } else
 #endif
-                    olsr_print_lq_neighbor4(msg_data, msg_tlen);
+                {
+                    if (olsr_print_lq_neighbor4(msg_data, msg_tlen) == -1)
+                        goto trunc;
+                }
             }
             break;