aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-09-22 02:56:23 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-22 02:56:23 -0400
commitba1ba25d3159573ffdc9e79e5c3dfcf9c5742964 (patch)
treec2572c4362e4ceaa7bfc6b2d6136d22026d37c40
parent290b774a1e0cb385658ba117452e2a2962323b1f (diff)
parent63c43787d35e45562a6b5927e2edc8f4783d95b8 (diff)
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>
-rw-r--r--include/net/xfrm.h4
-rw-r--r--net/ipv4/ip_vti.c15
-rw-r--r--net/ipv6/ip6_vti.c19
-rw-r--r--net/ipv6/xfrm6_input.c16
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/xfrm/xfrm_state.c1
-rw-r--r--net/xfrm/xfrm_user.c9
7 files changed, 51 insertions, 15 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index adfebd6f243c..17934312eecb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1540,8 +1540,10 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
1540void xfrm4_local_error(struct sk_buff *skb, u32 mtu); 1540void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
1541int xfrm6_extract_header(struct sk_buff *skb); 1541int xfrm6_extract_header(struct sk_buff *skb);
1542int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); 1542int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
1543int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); 1543int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
1544 struct ip6_tnl *t);
1544int xfrm6_transport_finish(struct sk_buff *skb, int async); 1545int xfrm6_transport_finish(struct sk_buff *skb, int async);
1546int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t);
1545int xfrm6_rcv(struct sk_buff *skb); 1547int xfrm6_rcv(struct sk_buff *skb);
1546int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, 1548int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
1547 xfrm_address_t *saddr, u8 proto); 1549 xfrm_address_t *saddr, u8 proto);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index cc701fa70b12..5d7944f394d9 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -88,6 +88,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
88 struct net_device *dev; 88 struct net_device *dev;
89 struct pcpu_sw_netstats *tstats; 89 struct pcpu_sw_netstats *tstats;
90 struct xfrm_state *x; 90 struct xfrm_state *x;
91 struct xfrm_mode *inner_mode;
91 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; 92 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
92 u32 orig_mark = skb->mark; 93 u32 orig_mark = skb->mark;
93 int ret; 94 int ret;
@@ -105,7 +106,19 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
105 } 106 }
106 107
107 x = xfrm_input_state(skb); 108 x = xfrm_input_state(skb);
108 family = x->inner_mode->afinfo->family; 109
110 inner_mode = x->inner_mode;
111
112 if (x->sel.family == AF_UNSPEC) {
113 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
114 if (inner_mode == NULL) {
115 XFRM_INC_STATS(dev_net(skb->dev),
116 LINUX_MIB_XFRMINSTATEMODEERROR);
117 return -EINVAL;
118 }
119 }
120
121 family = inner_mode->afinfo->family;
109 122
110 skb->mark = be32_to_cpu(tunnel->parms.i_key); 123 skb->mark = be32_to_cpu(tunnel->parms.i_key);
111 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); 124 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index d90a11f14040..5bd3afdcc771 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -321,11 +321,9 @@ static int vti6_rcv(struct sk_buff *skb)
321 goto discard; 321 goto discard;
322 } 322 }
323 323
324 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
325
326 rcu_read_unlock(); 324 rcu_read_unlock();
327 325
328 return xfrm6_rcv(skb); 326 return xfrm6_rcv_tnl(skb, t);
329 } 327 }
330 rcu_read_unlock(); 328 rcu_read_unlock();
331 return -EINVAL; 329 return -EINVAL;
@@ -340,6 +338,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
340 struct net_device *dev; 338 struct net_device *dev;
341 struct pcpu_sw_netstats *tstats; 339 struct pcpu_sw_netstats *tstats;
342 struct xfrm_state *x; 340 struct xfrm_state *x;
341 struct xfrm_mode *inner_mode;
343 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; 342 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
344 u32 orig_mark = skb->mark; 343 u32 orig_mark = skb->mark;
345 int ret; 344 int ret;
@@ -357,7 +356,19 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
357 } 356 }
358 357
359 x = xfrm_input_state(skb); 358 x = xfrm_input_state(skb);
360 family = x->inner_mode->afinfo->family; 359
360 inner_mode = x->inner_mode;
361
362 if (x->sel.family == AF_UNSPEC) {
363 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
364 if (inner_mode == NULL) {
365 XFRM_INC_STATS(dev_net(skb->dev),
366 LINUX_MIB_XFRMINSTATEMODEERROR);
367 return -EINVAL;
368 }
369 }
370
371 family = inner_mode->afinfo->family;
361 372
362 skb->mark = be32_to_cpu(t->parms.i_key); 373 skb->mark = be32_to_cpu(t->parms.i_key);
363 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); 374 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 00a2d40677d6..b5789562aded 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -21,9 +21,10 @@ int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb)
21 return xfrm6_extract_header(skb); 21 return xfrm6_extract_header(skb);
22} 22}
23 23
24int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) 24int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
25 struct ip6_tnl *t)
25{ 26{
26 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; 27 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
27 XFRM_SPI_SKB_CB(skb)->family = AF_INET6; 28 XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
28 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); 29 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
29 return xfrm_input(skb, nexthdr, spi, 0); 30 return xfrm_input(skb, nexthdr, spi, 0);
@@ -49,13 +50,18 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
49 return -1; 50 return -1;
50} 51}
51 52
52int xfrm6_rcv(struct sk_buff *skb) 53int xfrm6_rcv_tnl(struct sk_buff *skb, struct ip6_tnl *t)
53{ 54{
54 return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff], 55 return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
55 0); 56 0, t);
56} 57}
57EXPORT_SYMBOL(xfrm6_rcv); 58EXPORT_SYMBOL(xfrm6_rcv_tnl);
58 59
60int xfrm6_rcv(struct sk_buff *skb)
61{
62 return xfrm6_rcv_tnl(skb, NULL);
63}
64EXPORT_SYMBOL(xfrm6_rcv);
59int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, 65int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
60 xfrm_address_t *saddr, u8 proto) 66 xfrm_address_t *saddr, u8 proto)
61{ 67{
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 5743044cd660..e1c0bbe7996c 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -236,7 +236,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb)
236 __be32 spi; 236 __be32 spi;
237 237
238 spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr); 238 spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr);
239 return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi); 239 return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi, NULL);
240} 240}
241 241
242static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 242static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9895a8c56d8c..a30f898dc1c5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -332,6 +332,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
332{ 332{
333 tasklet_hrtimer_cancel(&x->mtimer); 333 tasklet_hrtimer_cancel(&x->mtimer);
334 del_timer_sync(&x->rtimer); 334 del_timer_sync(&x->rtimer);
335 kfree(x->aead);
335 kfree(x->aalg); 336 kfree(x->aalg);
336 kfree(x->ealg); 337 kfree(x->ealg);
337 kfree(x->calg); 338 kfree(x->calg);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index cb65d916a345..08892091cfe3 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -581,9 +581,12 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
581 if (err) 581 if (err)
582 goto error; 582 goto error;
583 583
584 if (attrs[XFRMA_SEC_CTX] && 584 if (attrs[XFRMA_SEC_CTX]) {
585 security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) 585 err = security_xfrm_state_alloc(x,
586 goto error; 586 nla_data(attrs[XFRMA_SEC_CTX]));
587 if (err)
588 goto error;
589 }
587 590
588 if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn, 591 if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
589 attrs[XFRMA_REPLAY_ESN_VAL]))) 592 attrs[XFRMA_REPLAY_ESN_VAL])))