Commit ba1ba25d authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 290b774a 63c43787
...@@ -1540,8 +1540,10 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); ...@@ -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);
......
...@@ -88,6 +88,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err) ...@@ -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) ...@@ -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);
......
...@@ -321,11 +321,9 @@ static int vti6_rcv(struct sk_buff *skb) ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -21,9 +21,10 @@ int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -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) ...@@ -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); EXPORT_SYMBOL(xfrm6_rcv_tnl);
int xfrm6_rcv(struct sk_buff *skb)
{
return xfrm6_rcv_tnl(skb, NULL);
}
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)
{ {
......
...@@ -236,7 +236,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) ...@@ -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,
......
...@@ -332,6 +332,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) ...@@ -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);
......
...@@ -581,9 +581,12 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, ...@@ -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,
nla_data(attrs[XFRMA_SEC_CTX]));
if (err)
goto error; 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])))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment