diff options
author | 2016-07-16 19:20:16 +0000 | |
---|---|---|
committer | 2016-07-16 19:20:16 +0000 | |
commit | a78ea73f827928c1e19cfa5f76567b253c6e1213 (patch) | |
tree | f9bae4266a6ef06e06fb3bf69fde2a5db58ba61f /usr.sbin/ldpd/labelmapping.c | |
parent | Fix sockopt name: ICMPV6_FILTER -> ICMP6_FILTER (diff) | |
download | wireguard-openbsd-a78ea73f827928c1e19cfa5f76567b253c6e1213.tar.xz wireguard-openbsd-a78ea73f827928c1e19cfa5f76567b253c6e1213.zip |
Fix parsing of mal-formed optional TLVs/Sub-TLVs.
We must detect if a TLV's length extends beyond the end of the containing
message. And, if so, send a fatal "Bad TLV Length" notification message.
Found with the Mu Dynamics Mu-8000 protocol fuzzer.
Diffstat (limited to 'usr.sbin/ldpd/labelmapping.c')
-rw-r--r-- | usr.sbin/ldpd/labelmapping.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c index a1ec305f0ca..f8261e6d6d8 100644 --- a/usr.sbin/ldpd/labelmapping.c +++ b/usr.sbin/ldpd/labelmapping.c @@ -1,4 +1,4 @@ -/* $OpenBSD: labelmapping.c,v 1.57 2016/07/15 17:09:25 renato Exp $ */ +/* $OpenBSD: labelmapping.c,v 1.58 2016/07/16 19:20:16 renato Exp $ */ /* * Copyright (c) 2014, 2015 Renato Westphal <renato@openbsd.org> @@ -246,9 +246,13 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) } memcpy(&tlv, buf, TLV_HDR_SIZE); + tlv_len = ntohs(tlv.length); + if (tlv_len + TLV_HDR_SIZE > len) { + session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type); + goto err; + } buf += TLV_HDR_SIZE; len -= TLV_HDR_SIZE; - tlv_len = ntohs(tlv.length); switch (ntohs(tlv.type)) { case TLV_TYPE_LABELREQUEST: @@ -334,10 +338,9 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type) } break; default: - if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) { + if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) send_notification_nbr(nbr, S_UNKNOWN_TLV, msg.id, msg.type); - } /* ignore unknown tlv */ break; } @@ -708,6 +711,12 @@ tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *msg, char *buf, } memcpy(&stlv, buf + off, sizeof(stlv)); + if (stlv.length > pw_len) { + session_shutdown(nbr, S_BAD_TLV_LEN, msg->id, + msg->type); + return (-1); + } + switch (stlv.type) { case SUBTLV_IFMTU: if (stlv.length != FEC_SUBTLV_IFMTU_SIZE) { |