From f023a2e03f4a8924b3b5ef0136e291549a4b814c Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Wed, 16 Aug 2023 11:14:39 +0300 Subject: [PATCH] bgpd: Treat-as-withdraw attribute if remaining data is not enough Relax this handling (RFC 7606) only for eBGP peers. More details: https://datatracker.ietf.org/doc/html/rfc7606#section-4 There are two error cases in which the Total Attribute Length value can be in conflict with the enclosed path attributes, which themselves carry length values: * In the first case, the length of the last encountered path attribute would cause the Total Attribute Length to be exceeded when parsing the enclosed path attributes. * In the second case, fewer than three octets remain (or fewer than four octets, if the Attribute Flags field has the Extended Length bit set) when beginning to parse the attribute. That is, this case exists if there remains unconsumed data in the path attributes but yet insufficient data to encode a single minimum- sized path attribute. <<<< HANDLING THIS CASE IN THIS COMMIT >>>> In either of these cases, an error condition exists and the "treat- as-withdraw" approach MUST be used (unless some other, more severe error is encountered dictating a stronger approach), and the Total Attribute Length MUST be relied upon to enable the beginning of the NLRI field to be located. Signed-off-by: Donatas Abraitis --- bgpd/bgp_attr.c | 50 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e07af4ab03..45536d2c5c 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -3461,8 +3461,24 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, /* Get attributes to the end of attribute length. */ while (BGP_INPUT_PNT(peer) < endp) { + startp = BGP_INPUT_PNT(peer); + + /* Fewer than three octets remain (or fewer than four + * octets, if the Attribute Flags field has the Extended + * Length bit set) when beginning to parse the attribute. + * That is, this case exists if there remains unconsumed + * data in the path attributes but yet insufficient data + * to encode a single minimum-sized path attribute. + * + * An error condition exists and the "treat-as-withdraw" + * approach MUST be used (unless some other, more severe + * error is encountered dictating a stronger approach), + * and the Total Attribute Length MUST be relied upon to + * enable the beginning of the NLRI field to be located. + */ + /* Check remaining length check.*/ - if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) { + if ((endp - startp) < BGP_ATTR_MIN_LEN) { /* XXX warning: long int format, int arg (arg 5) */ flog_warn( EC_BGP_ATTRIBUTE_TOO_SMALL, @@ -3471,17 +3487,22 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, (unsigned long)(endp - stream_pnt(BGP_INPUT(peer)))); - bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - ret = BGP_ATTR_PARSE_ERROR; + if (peer->sort != BGP_PEER_EBGP) { + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + ret = BGP_ATTR_PARSE_ERROR; + } else { + ret = BGP_ATTR_PARSE_WITHDRAW; + } + goto done; } - /* Fetch attribute flag and type. */ - startp = BGP_INPUT_PNT(peer); - /* "The lower-order four bits of the Attribute Flags octet are - unused. They MUST be zero when sent and MUST be ignored when - received." */ + /* Fetch attribute flag and type. + * The lower-order four bits of the Attribute Flags octet are + * unused. They MUST be zero when sent and MUST be ignored when + * received. + */ flag = 0xF0 & stream_getc(BGP_INPUT(peer)); type = stream_getc(BGP_INPUT(peer)); @@ -3495,9 +3516,14 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr, (unsigned long)(endp - stream_pnt(BGP_INPUT(peer)))); - bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - ret = BGP_ATTR_PARSE_ERROR; + if (peer->sort != BGP_PEER_EBGP) { + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + ret = BGP_ATTR_PARSE_ERROR; + } else { + ret = BGP_ATTR_PARSE_WITHDRAW; + } + goto done; } -- 2.39.5