diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2023-11-22 14:42:55 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-22 14:42:55 +0200 | 
| commit | f0ffd9b7b86a5c36eebc107d06c997ef171f57b9 (patch) | |
| tree | f30e9cb71f9dc6acd42647d79eb6b4df86ae7627 | |
| parent | 61bb5917cf715223f523afcd76c67450dc162d81 (diff) | |
| parent | a0c4ec2f52b299d45a77b0fcb29452329d22dce1 (diff) | |
Merge pull request #14852 from donaldsharp/backport_itis
Backport a couple of fixes to 8.5
| -rw-r--r-- | bgpd/bgp_attr.c | 34 | ||||
| -rw-r--r-- | bgpd/bgp_attr.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_packet.c | 7 | 
3 files changed, 29 insertions, 13 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 6700470612..7144c4bfa7 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -3406,19 +3406,13 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr,  	uint8_t type = 0;  	/* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an -	 * empty UPDATE.  */ +	 * empty UPDATE. Treat-as-withdraw, otherwise if we just ignore it, +	 * we will pass it to be processed as a normal UPDATE without mandatory +	 * attributes, that could lead to harmful behavior. +	 */  	if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag &&  	    !length) -		return BGP_ATTR_PARSE_PROCEED; - -	/* "An UPDATE message that contains the MP_UNREACH_NLRI is not required -	   to carry any other path attributes.", though if MP_REACH_NLRI or NLRI -	   are present, it should.  Check for any other attribute being present -	   instead. -	 */ -	if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) && -	     CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI)))) -		return BGP_ATTR_PARSE_PROCEED; +		return BGP_ATTR_PARSE_WITHDRAW;  	if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))  		type = BGP_ATTR_ORIGIN; @@ -3438,6 +3432,16 @@ static int bgp_attr_check(struct peer *peer, struct attr *attr,  	    && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))  		type = BGP_ATTR_LOCAL_PREF; +	/* An UPDATE message that contains the MP_UNREACH_NLRI is not required +	 * to carry any other path attributes. Though if MP_REACH_NLRI or NLRI +	 * are present, it should. Check for any other attribute being present +	 * instead. +	 */ +	if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) && +	    CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))) +		return type ? BGP_ATTR_PARSE_MISSING_MANDATORY +			    : BGP_ATTR_PARSE_PROCEED; +  	/* If any of the well-known mandatory attributes are not present  	 * in an UPDATE message, then "treat-as-withdraw" MUST be used.  	 */ @@ -3839,7 +3843,13 @@ done:  	aspath_unintern(&as4_path);  	transit = bgp_attr_get_transit(attr); -	if (ret != BGP_ATTR_PARSE_ERROR) { +	/* If we received an UPDATE with mandatory attributes, then +	 * the unrecognized transitive optional attribute of that +	 * path MUST be passed. Otherwise, it's an error, and from +	 * security perspective it might be very harmful if we continue +	 * here with the unrecognized attributes. +	 */ +	if (ret == BGP_ATTR_PARSE_PROCEED) {  		/* Finally intern unknown attribute. */  		if (transit)  			bgp_attr_set_transit(attr, transit_intern(transit)); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index ba8d4fc735..275965fe62 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -379,6 +379,7 @@ enum bgp_attr_parse_ret {  	/* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR  	 */  	BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3, +	BGP_ATTR_PARSE_MISSING_MANDATORY = -4,  };  struct bpacket_attr_vec_arr; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 5e0312a72d..59f895ac58 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1983,7 +1983,12 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)  	/* Network Layer Reachability Information. */  	update_len = end - stream_pnt(s); -	if (update_len && attribute_len) { +	/* If we received MP_UNREACH_NLRI attribute, but also NLRIs, then +	 * NLRIs should be handled as a new data. Though, if we received +	 * NLRIs without mandatory attributes, they should be ignored. +	 */ +	if (update_len && attribute_len && +	    attr_parse_ret != BGP_ATTR_PARSE_MISSING_MANDATORY) {  		/* Set NLRI portion to structure. */  		nlris[NLRI_UPDATE].afi = AFI_IP;  		nlris[NLRI_UPDATE].safi = SAFI_UNICAST;  | 
