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; }