2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-30 08:04:13 +08:00

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2018-05-07

1) 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.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-05-07 23:51:30 -04:00
commit 1822f638e8
5 changed files with 47 additions and 12 deletions

View File

@ -375,6 +375,7 @@ struct xfrm_input_afinfo {
int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo); int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo);
int xfrm_input_unregister_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); void xfrm_state_delete_tunnel(struct xfrm_state *x);
struct xfrm_type { struct xfrm_type {

View File

@ -669,7 +669,7 @@ static void vti6_link_config(struct ip6_tnl *t, bool keep_mtu)
else else
mtu = ETH_DATA_LEN - LL_MAX_HEADER - sizeof(struct ipv6hdr); 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->priv_destructor = vti6_dev_free;
dev->type = ARPHRD_TUNNEL6; 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->max_mtu = IP_MAX_MTU - sizeof(struct ipv6hdr);
dev->flags |= IFF_NOARP; dev->flags |= IFF_NOARP;
dev->addr_len = sizeof(struct in6_addr); dev->addr_len = sizeof(struct in6_addr);

View File

@ -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); struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
unsigned int i; unsigned int i;
xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
xfrm_flush_gc();
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i])); WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));

View File

@ -437,6 +437,24 @@ static int verify_address_len(const void *p)
return 0; 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) 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) + 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; return -EINVAL;
if (ext_hdrs[ext_type-1] != NULL) if (ext_hdrs[ext_type-1] != NULL)
return -EINVAL; return -EINVAL;
if (ext_type == SADB_EXT_ADDRESS_SRC || switch (ext_type) {
ext_type == SADB_EXT_ADDRESS_DST || case SADB_EXT_ADDRESS_SRC:
ext_type == SADB_EXT_ADDRESS_PROXY || case SADB_EXT_ADDRESS_DST:
ext_type == SADB_X_EXT_NAT_T_OA) { case SADB_EXT_ADDRESS_PROXY:
case SADB_X_EXT_NAT_T_OA:
if (verify_address_len(p)) if (verify_address_len(p))
return -EINVAL; return -EINVAL;
} break;
if (ext_type == SADB_X_EXT_SEC_CTX) { case SADB_X_EXT_SEC_CTX:
if (verify_sec_ctx_len(p)) if (verify_sec_ctx_len(p))
return -EINVAL; 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; 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]; key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
if (key != NULL && if (key != NULL &&
sa->sadb_sa_auth != SADB_X_AALG_NULL && sa->sadb_sa_auth != SADB_X_AALG_NULL &&
((key->sadb_key_bits+7) / 8 == 0 || key->sadb_key_bits == 0)
(key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
if (key != NULL && if (key != NULL &&
sa->sadb_sa_encrypt != SADB_EALG_NULL && sa->sadb_sa_encrypt != SADB_EALG_NULL &&
((key->sadb_key_bits+7) / 8 == 0 || key->sadb_key_bits == 0)
(key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
x = xfrm_state_alloc(net); x = xfrm_state_alloc(net);

View File

@ -2175,6 +2175,12 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
return afinfo; 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 */ /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
void xfrm_state_delete_tunnel(struct xfrm_state *x) void xfrm_state_delete_tunnel(struct xfrm_state *x)
{ {