aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-09 16:31:47 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:55:02 -0400
commit050f009e16f908932070313c1745d09dc69fd62b (patch)
tree2176b8034065bf2e8b401865efcfaab912bb1997 /net
parent68325d3b12ad5bce650c2883bb878257f197efff (diff)
[IPSEC]: Lock state when copying non-atomic fields to user-space
This patch adds locking so that when we're copying non-atomic fields such as life-time or coaddr to user-space we don't get a partial result. For af_key I've changed every instance of pfkey_xfrm_state2msg apart from expiration notification to include the keys and life-times. This is in-line with XFRM behaviour. The actual cases affected are: * pfkey_getspi: No change as we don't have any keys to copy. * key_notify_sa: + ADD/UPD: This wouldn't work otherwise. + DEL: It can't hurt. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/key/af_key.c35
-rw-r--r--net/xfrm/xfrm_user.c14
2 files changed, 33 insertions, 16 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 143d46f6329a..7969f8a716df 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -655,7 +655,8 @@ static inline int pfkey_mode_to_xfrm(int mode)
655 } 655 }
656} 656}
657 657
658static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc) 658static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
659 int add_keys, int hsc)
659{ 660{
660 struct sk_buff *skb; 661 struct sk_buff *skb;
661 struct sadb_msg *hdr; 662 struct sadb_msg *hdr;
@@ -1009,6 +1010,24 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
1009 return skb; 1010 return skb;
1010} 1011}
1011 1012
1013
1014static inline struct sk_buff *pfkey_xfrm_state2msg(struct xfrm_state *x)
1015{
1016 struct sk_buff *skb;
1017
1018 spin_lock_bh(&x->lock);
1019 skb = __pfkey_xfrm_state2msg(x, 1, 3);
1020 spin_unlock_bh(&x->lock);
1021
1022 return skb;
1023}
1024
1025static inline struct sk_buff *pfkey_xfrm_state2msg_expire(struct xfrm_state *x,
1026 int hsc)
1027{
1028 return __pfkey_xfrm_state2msg(x, 0, hsc);
1029}
1030
1012static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, 1031static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
1013 void **ext_hdrs) 1032 void **ext_hdrs)
1014{ 1033{
@@ -1322,7 +1341,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
1322 } 1341 }
1323 1342
1324 err = xfrm_alloc_spi(x, min_spi, max_spi); 1343 err = xfrm_alloc_spi(x, min_spi, max_spi);
1325 resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x, 0, 3); 1344 resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x);
1326 1345
1327 if (IS_ERR(resp_skb)) { 1346 if (IS_ERR(resp_skb)) {
1328 xfrm_state_put(x); 1347 xfrm_state_put(x);
@@ -1412,12 +1431,8 @@ static int key_notify_sa(struct xfrm_state *x, struct km_event *c)
1412{ 1431{
1413 struct sk_buff *skb; 1432 struct sk_buff *skb;
1414 struct sadb_msg *hdr; 1433 struct sadb_msg *hdr;
1415 int hsc = 3;
1416
1417 if (c->event == XFRM_MSG_DELSA)
1418 hsc = 0;
1419 1434
1420 skb = pfkey_xfrm_state2msg(x, 0, hsc); 1435 skb = pfkey_xfrm_state2msg(x);
1421 1436
1422 if (IS_ERR(skb)) 1437 if (IS_ERR(skb))
1423 return PTR_ERR(skb); 1438 return PTR_ERR(skb);
@@ -1529,7 +1544,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
1529 if (x == NULL) 1544 if (x == NULL)
1530 return -ESRCH; 1545 return -ESRCH;
1531 1546
1532 out_skb = pfkey_xfrm_state2msg(x, 1, 3); 1547 out_skb = pfkey_xfrm_state2msg(x);
1533 proto = x->id.proto; 1548 proto = x->id.proto;
1534 xfrm_state_put(x); 1549 xfrm_state_put(x);
1535 if (IS_ERR(out_skb)) 1550 if (IS_ERR(out_skb))
@@ -1709,7 +1724,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1709 struct sk_buff *out_skb; 1724 struct sk_buff *out_skb;
1710 struct sadb_msg *out_hdr; 1725 struct sadb_msg *out_hdr;
1711 1726
1712 out_skb = pfkey_xfrm_state2msg(x, 1, 3); 1727 out_skb = pfkey_xfrm_state2msg(x);
1713 if (IS_ERR(out_skb)) 1728 if (IS_ERR(out_skb))
1714 return PTR_ERR(out_skb); 1729 return PTR_ERR(out_skb);
1715 1730
@@ -2910,7 +2925,7 @@ static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c)
2910 else 2925 else
2911 hsc = 1; 2926 hsc = 1;
2912 2927
2913 out_skb = pfkey_xfrm_state2msg(x, 0, hsc); 2928 out_skb = pfkey_xfrm_state2msg_expire(x, hsc);
2914 if (IS_ERR(out_skb)) 2929 if (IS_ERR(out_skb))
2915 return PTR_ERR(out_skb); 2930 return PTR_ERR(out_skb);
2916 2931
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 2cbbe5e93a7b..5238f6a8dfad 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -507,8 +507,16 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
507 struct xfrm_usersa_info *p, 507 struct xfrm_usersa_info *p,
508 struct sk_buff *skb) 508 struct sk_buff *skb)
509{ 509{
510 spin_lock_bh(&x->lock);
510 copy_to_user_state(x, p); 511 copy_to_user_state(x, p);
511 512
513 if (x->coaddr)
514 NLA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
515
516 if (x->lastused)
517 NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused);
518 spin_unlock_bh(&x->lock);
519
512 if (x->aalg) 520 if (x->aalg)
513 NLA_PUT(skb, XFRMA_ALG_AUTH, alg_len(x->aalg), x->aalg); 521 NLA_PUT(skb, XFRMA_ALG_AUTH, alg_len(x->aalg), x->aalg);
514 if (x->ealg) 522 if (x->ealg)
@@ -522,12 +530,6 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
522 if (x->security && copy_sec_ctx(x->security, skb) < 0) 530 if (x->security && copy_sec_ctx(x->security, skb) < 0)
523 goto nla_put_failure; 531 goto nla_put_failure;
524 532
525 if (x->coaddr)
526 NLA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
527
528 if (x->lastused)
529 NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused);
530
531 return 0; 533 return 0;
532 534
533nla_put_failure: 535nla_put_failure: