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

Steffen Klassert says:

====================
pull request (net): ipsec 2016-09-21

1) Propagate errors on security context allocation.
   From Mathias Krause.

2) Fix inbound policy checks for inter address family tunnels.
   From Thomas Zeitlhofer.

3) Fix an old memory leak on aead algorithm usage.
   From Ilan Tayari.

4) A recent patch fixed a possible NULL pointer dereference
   but broke the vti6 input path.
   Fix from Nicolas Dichtel.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-09-22 02:56:23 -04:00
commit ba1ba25d31
7 changed files with 51 additions and 15 deletions

View File

@ -1540,8 +1540,10 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
void xfrm4_local_error(struct sk_buff *skb, u32 mtu); void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
int xfrm6_extract_header(struct sk_buff *skb); int xfrm6_extract_header(struct sk_buff *skb);
int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
struct ip6_tnl *t);
int xfrm6_transport_finish(struct sk_buff *skb, int async); int xfrm6_transport_finish(struct sk_buff *skb, int async);
int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t);
int xfrm6_rcv(struct sk_buff *skb); int xfrm6_rcv(struct sk_buff *skb);
int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto); xfrm_address_t *saddr, u8 proto);

View File

@ -88,6 +88,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
struct net_device *dev; struct net_device *dev;
struct pcpu_sw_netstats *tstats; struct pcpu_sw_netstats *tstats;
struct xfrm_state *x; struct xfrm_state *x;
struct xfrm_mode *inner_mode;
struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
u32 orig_mark = skb->mark; u32 orig_mark = skb->mark;
int ret; int ret;
@ -105,7 +106,19 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
} }
x = xfrm_input_state(skb); x = xfrm_input_state(skb);
family = x->inner_mode->afinfo->family;
inner_mode = x->inner_mode;
if (x->sel.family == AF_UNSPEC) {
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
if (inner_mode == NULL) {
XFRM_INC_STATS(dev_net(skb->dev),
LINUX_MIB_XFRMINSTATEMODEERROR);
return -EINVAL;
}
}
family = inner_mode->afinfo->family;
skb->mark = be32_to_cpu(tunnel->parms.i_key); skb->mark = be32_to_cpu(tunnel->parms.i_key);
ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);

View File

@ -321,11 +321,9 @@ static int vti6_rcv(struct sk_buff *skb)
goto discard; goto discard;
} }
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
rcu_read_unlock(); rcu_read_unlock();
return xfrm6_rcv(skb); return xfrm6_rcv_tnl(skb, t);
} }
rcu_read_unlock(); rcu_read_unlock();
return -EINVAL; return -EINVAL;
@ -340,6 +338,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
struct net_device *dev; struct net_device *dev;
struct pcpu_sw_netstats *tstats; struct pcpu_sw_netstats *tstats;
struct xfrm_state *x; struct xfrm_state *x;
struct xfrm_mode *inner_mode;
struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
u32 orig_mark = skb->mark; u32 orig_mark = skb->mark;
int ret; int ret;
@ -357,7 +356,19 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
} }
x = xfrm_input_state(skb); x = xfrm_input_state(skb);
family = x->inner_mode->afinfo->family;
inner_mode = x->inner_mode;
if (x->sel.family == AF_UNSPEC) {
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
if (inner_mode == NULL) {
XFRM_INC_STATS(dev_net(skb->dev),
LINUX_MIB_XFRMINSTATEMODEERROR);
return -EINVAL;
}
}
family = inner_mode->afinfo->family;
skb->mark = be32_to_cpu(t->parms.i_key); skb->mark = be32_to_cpu(t->parms.i_key);
ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);

View File

@ -21,9 +21,10 @@ int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb)
return xfrm6_extract_header(skb); return xfrm6_extract_header(skb);
} }
int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
struct ip6_tnl *t)
{ {
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
XFRM_SPI_SKB_CB(skb)->family = AF_INET6; XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
return xfrm_input(skb, nexthdr, spi, 0); return xfrm_input(skb, nexthdr, spi, 0);
@ -49,13 +50,18 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
return -1; return -1;
} }
int xfrm6_rcv(struct sk_buff *skb) int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t)
{ {
return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff], return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
0); 0, t);
}
EXPORT_SYMBOL(xfrm6_rcv_tnl);
int xfrm6_rcv(struct sk_buff *skb)
{
return xfrm6_rcv_tnl(skb, NULL);
} }
EXPORT_SYMBOL(xfrm6_rcv); EXPORT_SYMBOL(xfrm6_rcv);
int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto) xfrm_address_t *saddr, u8 proto)
{ {

View File

@ -236,7 +236,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb)
__be32 spi; __be32 spi;
spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr); spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr);
return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi); return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
} }
static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,

View File

@ -332,6 +332,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
{ {
tasklet_hrtimer_cancel(&x->mtimer); tasklet_hrtimer_cancel(&x->mtimer);
del_timer_sync(&x->rtimer); del_timer_sync(&x->rtimer);
kfree(x->aead);
kfree(x->aalg); kfree(x->aalg);
kfree(x->ealg); kfree(x->ealg);
kfree(x->calg); kfree(x->calg);

View File

@ -581,9 +581,12 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
if (err) if (err)
goto error; goto error;
if (attrs[XFRMA_SEC_CTX] && if (attrs[XFRMA_SEC_CTX]) {
security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) err = security_xfrm_state_alloc(x,
goto error; nla_data(attrs[XFRMA_SEC_CTX]));
if (err)
goto error;
}
if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn, if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
attrs[XFRMA_REPLAY_ESN_VAL]))) attrs[XFRMA_REPLAY_ESN_VAL])))