diff options
author | simon <simon@FreeBSD.org> | 2007-08-01 20:40:44 +0000 |
---|---|---|
committer | simon <simon@FreeBSD.org> | 2007-08-01 20:40:44 +0000 |
commit | 68a3d30d4eef678528761ead6b0743885324cdd0 (patch) | |
tree | e35c83d4b04507a0f3802a9cb6fcc2846a9968c8 /contrib | |
parent | dfbc1e9a3f32f077becf1bdf542db19279811d50 (diff) | |
download | FreeBSD-src-68a3d30d4eef678528761ead6b0743885324cdd0.zip FreeBSD-src-68a3d30d4eef678528761ead6b0743885324cdd0.tar.gz |
Correct buffer overflow in tcpdump(1).
Security: FreeBSD-SA-07:06.tcpdump
Security: CVE-2007-3798
Obtained from: tcpdump.org
Approved by: re (security blanket)
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/tcpdump/print-bgp.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/contrib/tcpdump/print-bgp.c b/contrib/tcpdump/print-bgp.c index d6377fb..3610b25 100644 --- a/contrib/tcpdump/print-bgp.c +++ b/contrib/tcpdump/print-bgp.c @@ -622,6 +622,26 @@ trunc: return -2; } +/* + * As I remember, some versions of systems have an snprintf() that + * returns -1 if the buffer would have overflowed. If the return + * value is negative, set buflen to 0, to indicate that we've filled + * the buffer up. + * + * If the return value is greater than buflen, that means that + * the buffer would have overflowed; again, set buflen to 0 in + * that case. + */ +#define UPDATE_BUF_BUFLEN(buf, buflen, strlen) \ + if (strlen<0) \ + buflen=0; \ + else if ((u_int)strlen>buflen) \ + buflen=0; \ + else { \ + buflen-=strlen; \ + buf+=strlen; \ + } + static int decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen) { @@ -632,11 +652,13 @@ decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen) tlen=plen; pptr+=2; TCHECK2(pptr[0],15); + buf[0]='\0'; strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u", bgp_vpn_rd_print(pptr), EXTRACT_16BITS(pptr+8), EXTRACT_16BITS(pptr+10), EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */ + UPDATE_BUF_BUFLEN(buf, buflen, strlen); pptr+=15; tlen-=15; @@ -652,23 +674,32 @@ decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen) switch(tlv_type) { case 1: - strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x", - tlv_type, - tlv_len); + if (buflen!=0) { + strlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x", + tlv_type, + tlv_len); + UPDATE_BUF_BUFLEN(buf, buflen, strlen); + } ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */ while (ttlv_len>0) { TCHECK(pptr[0]); - strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++); + if (buflen!=0) { + strlen=snprintf(buf,buflen, "%02x",*pptr++); + UPDATE_BUF_BUFLEN(buf, buflen, strlen); + } ttlv_len--; } break; default: - snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u", - tlv_type, - tlv_len); + if (buflen!=0) { + strlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u", + tlv_type, + tlv_len); + UPDATE_BUF_BUFLEN(buf, buflen, strlen); + } break; } - tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */ + tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */ } return plen+2; |