aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-05-28 23:41:35 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-28 23:41:35 -0400
commit5aab0e8a45e2c15930af9aea7f461bf57ad8efe3 (patch)
treea34c7d50b993bb5e97ab058e32c6a195de7ddae4 /net
parent210347e1846d391aea863fb69165a2d70581f838 (diff)
parentd55c670cbc54b2270a465cdc382ce71adae45785 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2015-05-28 1) Fix a race in xfrm_state_lookup_byspi, we need to take the refcount before we release xfrm_state_lock. From Li RongQing. 2) Fix IV generation on ESN state. We used just the low order sequence numbers for IV generation on ESN, as a result the IV can repeat on the same state. Fix this by using the high order sequence number bits too and make sure to always initialize the high order bits with zero. These patches are serious stable candidates. Fixes from Herbert Xu. 3) Fix the skb->mark handling on vti. We don't reset skb->mark in skb_scrub_packet anymore, so vti must care to restore the original value back after it was used to lookup the vti policy and state. Fixes from Alexander Duyck. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/esp4.c3
-rw-r--r--net/ipv4/ip_vti.c14
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/ip6_vti.c13
-rw-r--r--net/xfrm/xfrm_input.c17
-rw-r--r--net/xfrm/xfrm_replay.c2
-rw-r--r--net/xfrm/xfrm_state.c2
7 files changed, 43 insertions, 11 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 421a80b09b62..30b544f025ac 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -256,7 +256,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
256 aead_givcrypt_set_crypt(req, sg, sg, clen, iv); 256 aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
257 aead_givcrypt_set_assoc(req, asg, assoclen); 257 aead_givcrypt_set_assoc(req, asg, assoclen);
258 aead_givcrypt_set_giv(req, esph->enc_data, 258 aead_givcrypt_set_giv(req, esph->enc_data,
259 XFRM_SKB_CB(skb)->seq.output.low); 259 XFRM_SKB_CB(skb)->seq.output.low +
260 ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32));
260 261
261 ESP_SKB_CB(skb)->tmp = tmp; 262 ESP_SKB_CB(skb)->tmp = tmp;
262 err = crypto_aead_givencrypt(req); 263 err = crypto_aead_givencrypt(req);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 9f7269f3c54a..0c152087ca15 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -65,7 +65,6 @@ static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
65 goto drop; 65 goto drop;
66 66
67 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel; 67 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
68 skb->mark = be32_to_cpu(tunnel->parms.i_key);
69 68
70 return xfrm_input(skb, nexthdr, spi, encap_type); 69 return xfrm_input(skb, nexthdr, spi, encap_type);
71 } 70 }
@@ -91,6 +90,8 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
91 struct pcpu_sw_netstats *tstats; 90 struct pcpu_sw_netstats *tstats;
92 struct xfrm_state *x; 91 struct xfrm_state *x;
93 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; 92 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
93 u32 orig_mark = skb->mark;
94 int ret;
94 95
95 if (!tunnel) 96 if (!tunnel)
96 return 1; 97 return 1;
@@ -107,7 +108,11 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
107 x = xfrm_input_state(skb); 108 x = xfrm_input_state(skb);
108 family = x->inner_mode->afinfo->family; 109 family = x->inner_mode->afinfo->family;
109 110
110 if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) 111 skb->mark = be32_to_cpu(tunnel->parms.i_key);
112 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
113 skb->mark = orig_mark;
114
115 if (!ret)
111 return -EPERM; 116 return -EPERM;
112 117
113 skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev))); 118 skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev)));
@@ -216,8 +221,6 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
216 221
217 memset(&fl, 0, sizeof(fl)); 222 memset(&fl, 0, sizeof(fl));
218 223
219 skb->mark = be32_to_cpu(tunnel->parms.o_key);
220
221 switch (skb->protocol) { 224 switch (skb->protocol) {
222 case htons(ETH_P_IP): 225 case htons(ETH_P_IP):
223 xfrm_decode_session(skb, &fl, AF_INET); 226 xfrm_decode_session(skb, &fl, AF_INET);
@@ -233,6 +236,9 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
233 return NETDEV_TX_OK; 236 return NETDEV_TX_OK;
234 } 237 }
235 238
239 /* override mark with tunnel output key */
240 fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key);
241
236 return vti_xmit(skb, dev, &fl); 242 return vti_xmit(skb, dev, &fl);
237} 243}
238 244
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 31f1b5d5e2ef..7c07ce36aae2 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -248,7 +248,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
248 aead_givcrypt_set_crypt(req, sg, sg, clen, iv); 248 aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
249 aead_givcrypt_set_assoc(req, asg, assoclen); 249 aead_givcrypt_set_assoc(req, asg, assoclen);
250 aead_givcrypt_set_giv(req, esph->enc_data, 250 aead_givcrypt_set_giv(req, esph->enc_data,
251 XFRM_SKB_CB(skb)->seq.output.low); 251 XFRM_SKB_CB(skb)->seq.output.low +
252 ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32));
252 253
253 ESP_SKB_CB(skb)->tmp = tmp; 254 ESP_SKB_CB(skb)->tmp = tmp;
254 err = crypto_aead_givencrypt(req); 255 err = crypto_aead_givencrypt(req);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index ed9d681207fa..ff3bd863fa03 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -322,7 +322,6 @@ static int vti6_rcv(struct sk_buff *skb)
322 } 322 }
323 323
324 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t; 324 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t;
325 skb->mark = be32_to_cpu(t->parms.i_key);
326 325
327 rcu_read_unlock(); 326 rcu_read_unlock();
328 327
@@ -342,6 +341,8 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
342 struct pcpu_sw_netstats *tstats; 341 struct pcpu_sw_netstats *tstats;
343 struct xfrm_state *x; 342 struct xfrm_state *x;
344 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; 343 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
344 u32 orig_mark = skb->mark;
345 int ret;
345 346
346 if (!t) 347 if (!t)
347 return 1; 348 return 1;
@@ -358,7 +359,11 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
358 x = xfrm_input_state(skb); 359 x = xfrm_input_state(skb);
359 family = x->inner_mode->afinfo->family; 360 family = x->inner_mode->afinfo->family;
360 361
361 if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) 362 skb->mark = be32_to_cpu(t->parms.i_key);
363 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
364 skb->mark = orig_mark;
365
366 if (!ret)
362 return -EPERM; 367 return -EPERM;
363 368
364 skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev))); 369 skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev)));
@@ -495,7 +500,6 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
495 int ret; 500 int ret;
496 501
497 memset(&fl, 0, sizeof(fl)); 502 memset(&fl, 0, sizeof(fl));
498 skb->mark = be32_to_cpu(t->parms.o_key);
499 503
500 switch (skb->protocol) { 504 switch (skb->protocol) {
501 case htons(ETH_P_IPV6): 505 case htons(ETH_P_IPV6):
@@ -516,6 +520,9 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
516 goto tx_err; 520 goto tx_err;
517 } 521 }
518 522
523 /* override mark with tunnel output key */
524 fl.flowi_mark = be32_to_cpu(t->parms.o_key);
525
519 ret = vti6_xmit(skb, dev, &fl); 526 ret = vti6_xmit(skb, dev, &fl);
520 if (ret < 0) 527 if (ret < 0)
521 goto tx_err; 528 goto tx_err;
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 526c4feb3b50..b58286ecd156 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -13,6 +13,8 @@
13#include <net/dst.h> 13#include <net/dst.h>
14#include <net/ip.h> 14#include <net/ip.h>
15#include <net/xfrm.h> 15#include <net/xfrm.h>
16#include <net/ip_tunnels.h>
17#include <net/ip6_tunnel.h>
16 18
17static struct kmem_cache *secpath_cachep __read_mostly; 19static struct kmem_cache *secpath_cachep __read_mostly;
18 20
@@ -186,6 +188,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
186 struct xfrm_state *x = NULL; 188 struct xfrm_state *x = NULL;
187 xfrm_address_t *daddr; 189 xfrm_address_t *daddr;
188 struct xfrm_mode *inner_mode; 190 struct xfrm_mode *inner_mode;
191 u32 mark = skb->mark;
189 unsigned int family; 192 unsigned int family;
190 int decaps = 0; 193 int decaps = 0;
191 int async = 0; 194 int async = 0;
@@ -203,6 +206,18 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
203 XFRM_SPI_SKB_CB(skb)->daddroff); 206 XFRM_SPI_SKB_CB(skb)->daddroff);
204 family = XFRM_SPI_SKB_CB(skb)->family; 207 family = XFRM_SPI_SKB_CB(skb)->family;
205 208
209 /* if tunnel is present override skb->mark value with tunnel i_key */
210 if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4) {
211 switch (family) {
212 case AF_INET:
213 mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4->parms.i_key);
214 break;
215 case AF_INET6:
216 mark = be32_to_cpu(XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6->parms.i_key);
217 break;
218 }
219 }
220
206 /* Allocate new secpath or COW existing one. */ 221 /* Allocate new secpath or COW existing one. */
207 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { 222 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
208 struct sec_path *sp; 223 struct sec_path *sp;
@@ -229,7 +244,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
229 goto drop; 244 goto drop;
230 } 245 }
231 246
232 x = xfrm_state_lookup(net, skb->mark, daddr, spi, nexthdr, family); 247 x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family);
233 if (x == NULL) { 248 if (x == NULL) {
234 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); 249 XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
235 xfrm_audit_state_notfound(skb, family, spi, seq); 250 xfrm_audit_state_notfound(skb, family, spi, seq);
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index dab57daae408..4fd725a0c500 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -99,6 +99,7 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
99 99
100 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { 100 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
101 XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq; 101 XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
102 XFRM_SKB_CB(skb)->seq.output.hi = 0;
102 if (unlikely(x->replay.oseq == 0)) { 103 if (unlikely(x->replay.oseq == 0)) {
103 x->replay.oseq--; 104 x->replay.oseq--;
104 xfrm_audit_state_replay_overflow(x, skb); 105 xfrm_audit_state_replay_overflow(x, skb);
@@ -177,6 +178,7 @@ static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
177 178
178 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { 179 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
179 XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq; 180 XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
181 XFRM_SKB_CB(skb)->seq.output.hi = 0;
180 if (unlikely(replay_esn->oseq == 0)) { 182 if (unlikely(replay_esn->oseq == 0)) {
181 replay_esn->oseq--; 183 replay_esn->oseq--;
182 xfrm_audit_state_replay_overflow(x, skb); 184 xfrm_audit_state_replay_overflow(x, skb);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f5e39e35d73a..96688cd0f6f1 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -927,8 +927,8 @@ struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
927 x->id.spi != spi) 927 x->id.spi != spi)
928 continue; 928 continue;
929 929
930 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
931 xfrm_state_hold(x); 930 xfrm_state_hold(x);
931 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
932 return x; 932 return x;
933 } 933 }
934 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 934 spin_unlock_bh(&net->xfrm.xfrm_state_lock);