diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
| -rw-r--r-- | net/xfrm/xfrm_user.c | 26 | 
1 files changed, 25 insertions, 1 deletions
| diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 983b0233767b..bdb48e5dba04 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1419,11 +1419,14 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,  static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)  { +	u16 prev_family;  	int i;  	if (nr > XFRM_MAX_DEPTH)  		return -EINVAL; +	prev_family = family; +  	for (i = 0; i < nr; i++) {  		/* We never validated the ut->family value, so many  		 * applications simply leave it at zero.  The check was @@ -1435,6 +1438,12 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)  		if (!ut[i].family)  			ut[i].family = family; +		if ((ut[i].mode == XFRM_MODE_TRANSPORT) && +		    (ut[i].family != prev_family)) +			return -EINVAL; + +		prev_family = ut[i].family; +  		switch (ut[i].family) {  		case AF_INET:  			break; @@ -1445,6 +1454,21 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)  		default:  			return -EINVAL;  		} + +		switch (ut[i].id.proto) { +		case IPPROTO_AH: +		case IPPROTO_ESP: +		case IPPROTO_COMP: +#if IS_ENABLED(CONFIG_IPV6) +		case IPPROTO_ROUTING: +		case IPPROTO_DSTOPTS: +#endif +		case IPSEC_PROTO_ANY: +			break; +		default: +			return -EINVAL; +		} +  	}  	return 0; @@ -2470,7 +2494,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {  	[XFRMA_PROTO]		= { .type = NLA_U8 },  	[XFRMA_ADDRESS_FILTER]	= { .len = sizeof(struct xfrm_address_filter) },  	[XFRMA_OFFLOAD_DEV]	= { .len = sizeof(struct xfrm_user_offload) }, -	[XFRMA_OUTPUT_MARK]	= { .len = NLA_U32 }, +	[XFRMA_OUTPUT_MARK]	= { .type = NLA_U32 },  };  static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = { |