pull request (net): ipsec 2018-05-07
Subsystems (4)
Steffen Klassert
maintainer1) Always verify length of provided sadb_key to fix a slab-out-of-bounds read in pfkey_add. From Kevin Easton.
2) Make sure that all states are really deleted before we check that the state lists are empty. Otherwise we trigger a warning.
3) Fix MTU handling of the VTI6 interfaces on
interfamily tunnels. From Stefano Brivio.
Please pull or let me know if there are problems.
Thanks!
The following changes since commit 76327a35caabd1a932e83d6a42b967aa08584e5d:
dp83640: Ensure against premature access to PHY registers after reset (2018-04-08 19:58:52 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git master
for you to fetch changes up to b4331a681822b420511b3258f1c3db35001fde48:
vti6: Change minimum MTU to IPV4_MIN_MTU, vti6 can carry IPv4 too (2018-04-27 07:29:23 +0200)
----------------------------------------------------------------
Kevin Easton (1):
af_key: Always verify length of provided sadb_key
Stefano Brivio (1):
vti6: Change minimum MTU to IPV4_MIN_MTU, vti6 can carry IPv4 too
Steffen Klassert (1):
xfrm: Fix warning in xfrm6_tunnel_net_exit.
include/net/xfrm.h | 1 + net/ipv6/ip6_vti.c | 4 ++-- net/ipv6/xfrm6_tunnel.c | 3 +++ net/key/af_key.c | 45 +++++++++++++++++++++++++++++++++++---------- net/xfrm/xfrm_state.c | 6 ++++++ 5 files changed, 47 insertions(+), 12 deletions(-)
Steffen Klassert
maintainerPATCH 1/3 af_key: Always verify length of provided sadb_key
From: Kevin Easton <[email protected]>
Key extensions (struct sadb_key) include a user-specified number of key bits. The kernel uses that number to determine how much key data to copy out of the message in pfkey_msg2xfrm_state().
The length of the sadb_key message must be verified to be long enough, even in the case of SADB_X_AALG_NULL. Furthermore, the sadb_key_len value must be long enough to include both the key data and the struct sadb_key itself.
Introduce a helper function verify_key_len(), and call it from parse_exthdrs() where other exthdr types are similarly checked for correctness.
--- net/key/af_key.c | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-)
net/key/af_key.c +35 -10
@@ -437,6 +437,24 @@ static int verify_address_len(const void *p)return 0 ; } +static inline int sadb_key_len (const struct sadb_key *key) +{ +int key_bytes =DIV_ROUND_UP (key->sadb_key_bits,8 ); + +return DIV_ROUND_UP (sizeof (struct sadb_key ) + key_bytes, +sizeof (uint64_t )); +} + +static int verify_key_len (const void *p) +{ +const struct sadb_key *key = p; + +if (sadb_key_len (key) > key->sadb_key_len) +return -EINVAL ; + +return 0 ; +} +static inline int pfkey_sec_ctx_len (const struct sadb_x_sec_ctx *sec_ctx) { return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) +
@@ -533,16 +551,25 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void *return -EINVAL ;if (ext_hdrs[ext_type-1 ] !=NULL )return -EINVAL ; -if (ext_type ==SADB_EXT_ADDRESS_SRC || - ext_type ==SADB_EXT_ADDRESS_DST || - ext_type ==SADB_EXT_ADDRESS_PROXY || - ext_type ==SADB_X_EXT_NAT_T_OA ) { +switch (ext_type) { +case SADB_EXT_ADDRESS_SRC : +case SADB_EXT_ADDRESS_DST : +case SADB_EXT_ADDRESS_PROXY : +case SADB_X_EXT_NAT_T_OA :if (verify_address_len (p))return -EINVAL ; - } -if (ext_type ==SADB_X_EXT_SEC_CTX ) { +break ; +case SADB_X_EXT_SEC_CTX :if (verify_sec_ctx_len (p))return -EINVAL ; +break ; +case SADB_EXT_KEY_AUTH : +case SADB_EXT_KEY_ENCRYPT : +if (verify_key_len (p)) +return -EINVAL ; +break ; +default : +break ; } ext_hdrs[ext_type-1 ] = (void *) p; }
@@ -1104,14 +1131,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, key = ext_hdrs[SADB_EXT_KEY_AUTH -1 ];if (key !=NULL && sa->sadb_sa_auth !=SADB_X_AALG_NULL && - ((key->sadb_key_bits+7 ) /8 ==0 || - (key->sadb_key_bits+7 ) /8 > key->sadb_key_len *sizeof (uint64_t ))) + key->sadb_key_bits ==0 )return ERR_PTR (-EINVAL ); key = ext_hdrs[SADB_EXT_KEY_ENCRYPT -1 ];if (key !=NULL && sa->sadb_sa_encrypt !=SADB_EALG_NULL && - ((key->sadb_key_bits+7 ) /8 ==0 || - (key->sadb_key_bits+7 ) /8 > key->sadb_key_len *sizeof (uint64_t ))) + key->sadb_key_bits ==0 )return ERR_PTR (-EINVAL ); x =xfrm_state_alloc (net);
Signature · 1 line
2.14.1
Steffen Klassert
maintainerPATCH 2/3 xfrm: Fix warning in xfrm6_tunnel_net_exit.
In reply to Steffen KlassertWe need to make sure that all states are really deleted before we check that the state lists are empty. Otherwise we trigger a warning.
--- include/net/xfrm.h | 1 + net/ipv6/xfrm6_tunnel.c | 3 +++ net/xfrm/xfrm_state.c | 6 ++++++ 3 files changed, 10 insertions(+)
include/net/xfrm.h +1 -0
@@ -375,6 +375,7 @@ struct xfrm_input_afinfo {int xfrm_input_register_afinfo (const struct xfrm_input_afinfo *afinfo);int xfrm_input_unregister_afinfo (const struct xfrm_input_afinfo *afinfo); +void xfrm_flush_gc (void );void xfrm_state_delete_tunnel (struct xfrm_state *x);struct xfrm_type {
net/ipv6/xfrm6_tunnel.c +3 -0
@@ -341,6 +341,9 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)struct xfrm6_tunnel_net *xfrm6_tn =xfrm6_tunnel_pernet (net);unsigned int i; +xfrm_state_flush (net,IPSEC_PROTO_ANY , false); +xfrm_flush_gc (); +for (i =0 ; i <XFRM6_TUNNEL_SPI_BYADDR_HSIZE ; i++)WARN_ON_ONCE (!hlist_empty (&xfrm6_tn->spi_byaddr[i]));
net/xfrm/xfrm_state.c +6 -0
@@ -2175,6 +2175,12 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)return afinfo; } +void xfrm_flush_gc (void ) +{ +flush_work (&xfrm_state_gc_work); +} +EXPORT_SYMBOL (xfrm_flush_gc); +/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ void xfrm_state_delete_tunnel (struct xfrm_state *x) {
Signature · 1 line
2.14.1
Steffen Klassert
maintainerPATCH 3/3 vti6: Change minimum MTU to IPV4_MIN_MTU, vti6 can carry IPv4 too
In reply to Steffen KlassertFrom: Stefano Brivio <[email protected]>
A vti6 interface can carry IPv4 as well, so it makes no sense to enforce a minimum MTU of IPV6_MIN_MTU.
If the user sets an MTU below IPV6_MIN_MTU, IPv6 will be disabled on the interface, courtesy of addrconf_notify().
--- net/ipv6/ip6_vti.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv6/ip6_vti.c +2 -2
@@ -669,7 +669,7 @@ static void vti6_link_config(struct ip6_tnl *t, bool keep_mtu)else mtu =ETH_DATA_LEN -LL_MAX_HEADER -sizeof (struct ipv6hdr ); - dev->mtu =max_t (int, mtu,IPV6_MIN_MTU ); + dev->mtu =max_t (int, mtu,IPV4_MIN_MTU ); }/**
@@ -881,7 +881,7 @@ static void vti6_dev_setup(struct net_device *dev) dev->priv_destructor = vti6_dev_free; dev->type =ARPHRD_TUNNEL6 ; - dev->min_mtu =IPV6_MIN_MTU ; + dev->min_mtu =IPV4_MIN_MTU ; dev->max_mtu =IP_MAX_MTU -sizeof (struct ipv6hdr ); dev->flags |=IFF_NOARP ; dev->addr_len =sizeof (struct in6_addr );
Signature · 1 line
2.14.1
David Miller
maintainerFrom: Steffen Klassert <[email protected]>
Date: Mon, 7 May 2018 10:43:20 +0200
Quoted 11 lines
1) Always verify length of provided
sadb_keyto fix a slab-out-of-bounds read inpfkey_add. From Kevin Easton.2) Make sure that all states are really deleted before we check that the state lists are empty. Otherwise we trigger a warning.
3) Fix MTU handling of the VTI6 interfaces on
interfamily tunnels. From Stefano Brivio.Please pull or let me know if there are problems.
Pulled, thanks Steffen.