Fix multiple possible segfaults in the IPsec printer that could occur
when EH/ESP/IPCOMP data extends past the captured length.

ah_print(), esp_print(), and ipcomp_print now check if their header
length will fall beyond the snapend boundry before accessing its
members.

ah_print() also additionally checks if the next header content will
extend past the snapend boundry before printing the next payload.
(This extends an existing truncation check.)

Finally, changed the existing ah_print() payload printing length check
to take into account that ah_hdr is not part of the payload length.
This should make the orginal length check more effective/correct.
Index: print-ipsec.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-ipsec.c,v
retrieving revision 1.22
diff -u -p -r1.22 print-ipsec.c
--- print-ipsec.c       11 Oct 2015 03:23:28 -0000      1.22
+++ print-ipsec.c       8 Nov 2015 17:55:59 -0000
@@ -222,7 +222,8 @@ esp_print (register const u_char *bp, re
                    ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst));
        }
 
-       if (plen < sizeof(struct esp_hdr)) {
+       if (plen < sizeof(struct esp_hdr) ||
+           bp + sizeof(struct esp_hdr) > snapend) {
                printf("[|esp]");
                return;
        }
@@ -270,7 +271,8 @@ ah_print (register const u_char *bp, reg
                    ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst));
        }
 
-       if (pl_len < sizeof(struct ah_hdr)) {
+       if (pl_len < sizeof(struct ah_hdr) ||
+           bp + sizeof(struct ah_hdr) > snapend) {
                printf("[|ah]");
                return;
        }
@@ -284,7 +286,8 @@ ah_print (register const u_char *bp, reg
 
                pl_len = (ah->ah_pl_len + 2) << 2; /* RFC2402, sec 2.2 */
 
-               if (len <= pl_len) {
+               if (len - sizeof(struct ah_hdr) < pl_len ||
+                   bp + pl_len > snapend) {
                        (void)printf("truncated");
                        goto out;
                }
@@ -354,7 +357,8 @@ ipcomp_print (register const u_char *bp,
        printf("ipcomp %s > %s",
            ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst));
 
-       if (plen < sizeof(struct ipcomp_hdr)) {
+       if (plen < sizeof(struct ipcomp_hdr) ||
+           bp + sizeof(struct ipcomp_hdr) > snapend) {
                printf("[|ipcomp]");
                return;
        }

Reply via email to