diff options
-rw-r--r-- | net/ipv4/esp4.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_vti.c | 14 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 3 | ||||
-rw-r--r-- | net/ipv6/ip6_vti.c | 13 | ||||
-rw-r--r-- | net/xfrm/xfrm_input.c | 17 | ||||
-rw-r--r-- | net/xfrm/xfrm_replay.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 2 |
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 | ||
17 | static struct kmem_cache *secpath_cachep __read_mostly; | 19 | static 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); |