mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-02 07:04:24 +00: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:
commit
1822f638e8
5 changed files with 47 additions and 12 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue