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