diff options
Diffstat (limited to 'net/ipv6/route.c')
| -rw-r--r-- | net/ipv6/route.c | 32 | 
1 files changed, 30 insertions, 2 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 42d60c76d30a..1deb6297aab6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -5224,6 +5224,19 @@ out:  	return should_notify;  } +static int fib6_gw_from_attr(struct in6_addr *gw, struct nlattr *nla, +			     struct netlink_ext_ack *extack) +{ +	if (nla_len(nla) < sizeof(*gw)) { +		NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_GATEWAY"); +		return -EINVAL; +	} + +	*gw = nla_get_in6_addr(nla); + +	return 0; +} +  static int ip6_route_multipath_add(struct fib6_config *cfg,  				   struct netlink_ext_ack *extack)  { @@ -5264,10 +5277,18 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,  			nla = nla_find(attrs, attrlen, RTA_GATEWAY);  			if (nla) { -				r_cfg.fc_gateway = nla_get_in6_addr(nla); +				err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, +							extack); +				if (err) +					goto cleanup; +  				r_cfg.fc_flags |= RTF_GATEWAY;  			}  			r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); + +			/* RTA_ENCAP_TYPE length checked in +			 * lwtunnel_valid_encap_type_attr +			 */  			nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);  			if (nla)  				r_cfg.fc_encap_type = nla_get_u16(nla); @@ -5434,7 +5455,13 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,  			nla = nla_find(attrs, attrlen, RTA_GATEWAY);  			if (nla) { -				nla_memcpy(&r_cfg.fc_gateway, nla, 16); +				err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, +							extack); +				if (err) { +					last_err = err; +					goto next_rtnh; +				} +  				r_cfg.fc_flags |= RTF_GATEWAY;  			}  		} @@ -5442,6 +5469,7 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,  		if (err)  			last_err = err; +next_rtnh:  		rtnh = rtnh_next(rtnh, &remaining);  	}  |