aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_algo.c6
-rw-r--r--net/xfrm/xfrm_policy.c154
-rw-r--r--net/xfrm/xfrm_state.c14
-rw-r--r--net/xfrm/xfrm_user.c149
4 files changed, 261 insertions, 62 deletions
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 2f4531fcac..6ed3302312 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -540,8 +540,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
540 start = end; 540 start = end;
541 } 541 }
542 } 542 }
543 if (len) 543 BUG_ON(len);
544 BUG();
545} 544}
546EXPORT_SYMBOL_GPL(skb_icv_walk); 545EXPORT_SYMBOL_GPL(skb_icv_walk);
547 546
@@ -610,8 +609,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
610 start = end; 609 start = end;
611 } 610 }
612 } 611 }
613 if (len) 612 BUG_ON(len);
614 BUG();
615 return elt; 613 return elt;
616} 614}
617EXPORT_SYMBOL_GPL(skb_to_sgvec); 615EXPORT_SYMBOL_GPL(skb_to_sgvec);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 0db9e57013..077bbf9fb9 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -10,7 +10,7 @@
10 * YOSHIFUJI Hideaki 10 * YOSHIFUJI Hideaki
11 * Split up af-specific portion 11 * Split up af-specific portion
12 * Derek Atkins <derek@ihtfp.com> Add the post_input processor 12 * Derek Atkins <derek@ihtfp.com> Add the post_input processor
13 * 13 *
14 */ 14 */
15 15
16#include <asm/bug.h> 16#include <asm/bug.h>
@@ -22,6 +22,7 @@
22#include <linux/workqueue.h> 22#include <linux/workqueue.h>
23#include <linux/notifier.h> 23#include <linux/notifier.h>
24#include <linux/netdevice.h> 24#include <linux/netdevice.h>
25#include <linux/netfilter.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <net/xfrm.h> 27#include <net/xfrm.h>
27#include <net/ip.h> 28#include <net/ip.h>
@@ -247,15 +248,14 @@ EXPORT_SYMBOL(xfrm_policy_alloc);
247 248
248void __xfrm_policy_destroy(struct xfrm_policy *policy) 249void __xfrm_policy_destroy(struct xfrm_policy *policy)
249{ 250{
250 if (!policy->dead) 251 BUG_ON(!policy->dead);
251 BUG();
252 252
253 if (policy->bundles) 253 BUG_ON(policy->bundles);
254 BUG();
255 254
256 if (del_timer(&policy->timer)) 255 if (del_timer(&policy->timer))
257 BUG(); 256 BUG();
258 257
258 security_xfrm_policy_free(policy);
259 kfree(policy); 259 kfree(policy);
260} 260}
261EXPORT_SYMBOL(__xfrm_policy_destroy); 261EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -346,10 +346,12 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
346 struct xfrm_policy *pol, **p; 346 struct xfrm_policy *pol, **p;
347 struct xfrm_policy *delpol = NULL; 347 struct xfrm_policy *delpol = NULL;
348 struct xfrm_policy **newpos = NULL; 348 struct xfrm_policy **newpos = NULL;
349 struct dst_entry *gc_list;
349 350
350 write_lock_bh(&xfrm_policy_lock); 351 write_lock_bh(&xfrm_policy_lock);
351 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { 352 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
352 if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) { 353 if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 &&
354 xfrm_sec_ctx_match(pol->security, policy->security)) {
353 if (excl) { 355 if (excl) {
354 write_unlock_bh(&xfrm_policy_lock); 356 write_unlock_bh(&xfrm_policy_lock);
355 return -EEXIST; 357 return -EEXIST;
@@ -381,21 +383,49 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
381 xfrm_pol_hold(policy); 383 xfrm_pol_hold(policy);
382 write_unlock_bh(&xfrm_policy_lock); 384 write_unlock_bh(&xfrm_policy_lock);
383 385
384 if (delpol) { 386 if (delpol)
385 xfrm_policy_kill(delpol); 387 xfrm_policy_kill(delpol);
388
389 read_lock_bh(&xfrm_policy_lock);
390 gc_list = NULL;
391 for (policy = policy->next; policy; policy = policy->next) {
392 struct dst_entry *dst;
393
394 write_lock(&policy->lock);
395 dst = policy->bundles;
396 if (dst) {
397 struct dst_entry *tail = dst;
398 while (tail->next)
399 tail = tail->next;
400 tail->next = gc_list;
401 gc_list = dst;
402
403 policy->bundles = NULL;
404 }
405 write_unlock(&policy->lock);
406 }
407 read_unlock_bh(&xfrm_policy_lock);
408
409 while (gc_list) {
410 struct dst_entry *dst = gc_list;
411
412 gc_list = dst->next;
413 dst_free(dst);
386 } 414 }
415
387 return 0; 416 return 0;
388} 417}
389EXPORT_SYMBOL(xfrm_policy_insert); 418EXPORT_SYMBOL(xfrm_policy_insert);
390 419
391struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, 420struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
392 int delete) 421 struct xfrm_sec_ctx *ctx, int delete)
393{ 422{
394 struct xfrm_policy *pol, **p; 423 struct xfrm_policy *pol, **p;
395 424
396 write_lock_bh(&xfrm_policy_lock); 425 write_lock_bh(&xfrm_policy_lock);
397 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { 426 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
398 if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) { 427 if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) &&
428 (xfrm_sec_ctx_match(ctx, pol->security))) {
399 xfrm_pol_hold(pol); 429 xfrm_pol_hold(pol);
400 if (delete) 430 if (delete)
401 *p = pol->next; 431 *p = pol->next;
@@ -410,7 +440,7 @@ struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
410 } 440 }
411 return pol; 441 return pol;
412} 442}
413EXPORT_SYMBOL(xfrm_policy_bysel); 443EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
414 444
415struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) 445struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
416{ 446{
@@ -491,7 +521,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
491 521
492/* Find policy to apply to this flow. */ 522/* Find policy to apply to this flow. */
493 523
494static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, 524static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir,
495 void **objp, atomic_t **obj_refp) 525 void **objp, atomic_t **obj_refp)
496{ 526{
497 struct xfrm_policy *pol; 527 struct xfrm_policy *pol;
@@ -505,9 +535,12 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
505 continue; 535 continue;
506 536
507 match = xfrm_selector_match(sel, fl, family); 537 match = xfrm_selector_match(sel, fl, family);
538
508 if (match) { 539 if (match) {
509 xfrm_pol_hold(pol); 540 if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) {
510 break; 541 xfrm_pol_hold(pol);
542 break;
543 }
511 } 544 }
512 } 545 }
513 read_unlock_bh(&xfrm_policy_lock); 546 read_unlock_bh(&xfrm_policy_lock);
@@ -515,15 +548,37 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
515 *obj_refp = &pol->refcnt; 548 *obj_refp = &pol->refcnt;
516} 549}
517 550
518static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl) 551static inline int policy_to_flow_dir(int dir)
552{
553 if (XFRM_POLICY_IN == FLOW_DIR_IN &&
554 XFRM_POLICY_OUT == FLOW_DIR_OUT &&
555 XFRM_POLICY_FWD == FLOW_DIR_FWD)
556 return dir;
557 switch (dir) {
558 default:
559 case XFRM_POLICY_IN:
560 return FLOW_DIR_IN;
561 case XFRM_POLICY_OUT:
562 return FLOW_DIR_OUT;
563 case XFRM_POLICY_FWD:
564 return FLOW_DIR_FWD;
565 };
566}
567
568static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid)
519{ 569{
520 struct xfrm_policy *pol; 570 struct xfrm_policy *pol;
521 571
522 read_lock_bh(&xfrm_policy_lock); 572 read_lock_bh(&xfrm_policy_lock);
523 if ((pol = sk->sk_policy[dir]) != NULL) { 573 if ((pol = sk->sk_policy[dir]) != NULL) {
524 int match = xfrm_selector_match(&pol->selector, fl, 574 int match = xfrm_selector_match(&pol->selector, fl,
525 sk->sk_family); 575 sk->sk_family);
576 int err = 0;
577
526 if (match) 578 if (match)
579 err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir));
580
581 if (match && !err)
527 xfrm_pol_hold(pol); 582 xfrm_pol_hold(pol);
528 else 583 else
529 pol = NULL; 584 pol = NULL;
@@ -596,6 +651,10 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
596 651
597 if (newp) { 652 if (newp) {
598 newp->selector = old->selector; 653 newp->selector = old->selector;
654 if (security_xfrm_policy_clone(old, newp)) {
655 kfree(newp);
656 return NULL; /* ENOMEM */
657 }
599 newp->lft = old->lft; 658 newp->lft = old->lft;
600 newp->curlft = old->curlft; 659 newp->curlft = old->curlft;
601 newp->action = old->action; 660 newp->action = old->action;
@@ -707,22 +766,6 @@ xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
707 return err; 766 return err;
708} 767}
709 768
710static inline int policy_to_flow_dir(int dir)
711{
712 if (XFRM_POLICY_IN == FLOW_DIR_IN &&
713 XFRM_POLICY_OUT == FLOW_DIR_OUT &&
714 XFRM_POLICY_FWD == FLOW_DIR_FWD)
715 return dir;
716 switch (dir) {
717 default:
718 case XFRM_POLICY_IN:
719 return FLOW_DIR_IN;
720 case XFRM_POLICY_OUT:
721 return FLOW_DIR_OUT;
722 case XFRM_POLICY_FWD:
723 return FLOW_DIR_FWD;
724 };
725}
726 769
727static int stale_bundle(struct dst_entry *dst); 770static int stale_bundle(struct dst_entry *dst);
728 771
@@ -741,19 +784,20 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
741 int err; 784 int err;
742 u32 genid; 785 u32 genid;
743 u16 family = dst_orig->ops->family; 786 u16 family = dst_orig->ops->family;
787 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
788 u32 sk_sid = security_sk_sid(sk, fl, dir);
744restart: 789restart:
745 genid = atomic_read(&flow_cache_genid); 790 genid = atomic_read(&flow_cache_genid);
746 policy = NULL; 791 policy = NULL;
747 if (sk && sk->sk_policy[1]) 792 if (sk && sk->sk_policy[1])
748 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); 793 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid);
749 794
750 if (!policy) { 795 if (!policy) {
751 /* To accelerate a bit... */ 796 /* To accelerate a bit... */
752 if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) 797 if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
753 return 0; 798 return 0;
754 799
755 policy = flow_cache_lookup(fl, family, 800 policy = flow_cache_lookup(fl, sk_sid, family, dir,
756 policy_to_flow_dir(XFRM_POLICY_OUT),
757 xfrm_policy_lookup); 801 xfrm_policy_lookup);
758 } 802 }
759 803
@@ -906,8 +950,8 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
906 return start; 950 return start;
907} 951}
908 952
909static int 953int
910_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) 954xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
911{ 955{
912 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); 956 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
913 957
@@ -918,6 +962,7 @@ _decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
918 xfrm_policy_put_afinfo(afinfo); 962 xfrm_policy_put_afinfo(afinfo);
919 return 0; 963 return 0;
920} 964}
965EXPORT_SYMBOL(xfrm_decode_session);
921 966
922static inline int secpath_has_tunnel(struct sec_path *sp, int k) 967static inline int secpath_has_tunnel(struct sec_path *sp, int k)
923{ 968{
@@ -934,16 +979,21 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
934{ 979{
935 struct xfrm_policy *pol; 980 struct xfrm_policy *pol;
936 struct flowi fl; 981 struct flowi fl;
982 u8 fl_dir = policy_to_flow_dir(dir);
983 u32 sk_sid;
937 984
938 if (_decode_session(skb, &fl, family) < 0) 985 if (xfrm_decode_session(skb, &fl, family) < 0)
939 return 0; 986 return 0;
987 nf_nat_decode_session(skb, &fl, family);
988
989 sk_sid = security_sk_sid(sk, &fl, fl_dir);
940 990
941 /* First, check used SA against their selectors. */ 991 /* First, check used SA against their selectors. */
942 if (skb->sp) { 992 if (skb->sp) {
943 int i; 993 int i;
944 994
945 for (i=skb->sp->len-1; i>=0; i--) { 995 for (i=skb->sp->len-1; i>=0; i--) {
946 struct sec_decap_state *xvec = &(skb->sp->x[i]); 996 struct sec_decap_state *xvec = &(skb->sp->x[i]);
947 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) 997 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
948 return 0; 998 return 0;
949 999
@@ -958,11 +1008,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
958 1008
959 pol = NULL; 1009 pol = NULL;
960 if (sk && sk->sk_policy[dir]) 1010 if (sk && sk->sk_policy[dir])
961 pol = xfrm_sk_policy_lookup(sk, dir, &fl); 1011 pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid);
962 1012
963 if (!pol) 1013 if (!pol)
964 pol = flow_cache_lookup(&fl, family, 1014 pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir,
965 policy_to_flow_dir(dir),
966 xfrm_policy_lookup); 1015 xfrm_policy_lookup);
967 1016
968 if (!pol) 1017 if (!pol)
@@ -1007,20 +1056,19 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
1007{ 1056{
1008 struct flowi fl; 1057 struct flowi fl;
1009 1058
1010 if (_decode_session(skb, &fl, family) < 0) 1059 if (xfrm_decode_session(skb, &fl, family) < 0)
1011 return 0; 1060 return 0;
1012 1061
1013 return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; 1062 return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
1014} 1063}
1015EXPORT_SYMBOL(__xfrm_route_forward); 1064EXPORT_SYMBOL(__xfrm_route_forward);
1016 1065
1017/* Optimize later using cookies and generation ids. */
1018
1019static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) 1066static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
1020{ 1067{
1021 if (!stale_bundle(dst)) 1068 /* If it is marked obsolete, which is how we even get here,
1022 return dst; 1069 * then we have purged it from the policy bundle list and we
1023 1070 * did that for a good reason.
1071 */
1024 return NULL; 1072 return NULL;
1025} 1073}
1026 1074
@@ -1104,6 +1152,16 @@ int xfrm_flush_bundles(void)
1104 return 0; 1152 return 0;
1105} 1153}
1106 1154
1155static int always_true(struct dst_entry *dst)
1156{
1157 return 1;
1158}
1159
1160void xfrm_flush_all_bundles(void)
1161{
1162 xfrm_prune_bundles(always_true);
1163}
1164
1107void xfrm_init_pmtu(struct dst_entry *dst) 1165void xfrm_init_pmtu(struct dst_entry *dst)
1108{ 1166{
1109 do { 1167 do {
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 7cf48aa6c9..e12d0be5f9 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -10,7 +10,7 @@
10 * Split up af-specific functions 10 * Split up af-specific functions
11 * Derek Atkins <derek@ihtfp.com> 11 * Derek Atkins <derek@ihtfp.com>
12 * Add UDP Encapsulation 12 * Add UDP Encapsulation
13 * 13 *
14 */ 14 */
15 15
16#include <linux/workqueue.h> 16#include <linux/workqueue.h>
@@ -70,6 +70,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
70 x->type->destructor(x); 70 x->type->destructor(x);
71 xfrm_put_type(x->type); 71 xfrm_put_type(x->type);
72 } 72 }
73 security_xfrm_state_free(x);
73 kfree(x); 74 kfree(x);
74} 75}
75 76
@@ -343,7 +344,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
343 selector. 344 selector.
344 */ 345 */
345 if (x->km.state == XFRM_STATE_VALID) { 346 if (x->km.state == XFRM_STATE_VALID) {
346 if (!xfrm_selector_match(&x->sel, fl, family)) 347 if (!xfrm_selector_match(&x->sel, fl, family) ||
348 !xfrm_sec_ctx_match(pol->security, x->security))
347 continue; 349 continue;
348 if (!best || 350 if (!best ||
349 best->km.dying > x->km.dying || 351 best->km.dying > x->km.dying ||
@@ -354,7 +356,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
354 acquire_in_progress = 1; 356 acquire_in_progress = 1;
355 } else if (x->km.state == XFRM_STATE_ERROR || 357 } else if (x->km.state == XFRM_STATE_ERROR ||
356 x->km.state == XFRM_STATE_EXPIRED) { 358 x->km.state == XFRM_STATE_EXPIRED) {
357 if (xfrm_selector_match(&x->sel, fl, family)) 359 if (xfrm_selector_match(&x->sel, fl, family) &&
360 xfrm_sec_ctx_match(pol->security, x->security))
358 error = -ESRCH; 361 error = -ESRCH;
359 } 362 }
360 } 363 }
@@ -431,6 +434,8 @@ void xfrm_state_insert(struct xfrm_state *x)
431 spin_lock_bh(&xfrm_state_lock); 434 spin_lock_bh(&xfrm_state_lock);
432 __xfrm_state_insert(x); 435 __xfrm_state_insert(x);
433 spin_unlock_bh(&xfrm_state_lock); 436 spin_unlock_bh(&xfrm_state_lock);
437
438 xfrm_flush_all_bundles();
434} 439}
435EXPORT_SYMBOL(xfrm_state_insert); 440EXPORT_SYMBOL(xfrm_state_insert);
436 441
@@ -478,6 +483,9 @@ out:
478 spin_unlock_bh(&xfrm_state_lock); 483 spin_unlock_bh(&xfrm_state_lock);
479 xfrm_state_put_afinfo(afinfo); 484 xfrm_state_put_afinfo(afinfo);
480 485
486 if (!err)
487 xfrm_flush_all_bundles();
488
481 if (x1) { 489 if (x1) {
482 xfrm_state_delete(x1); 490 xfrm_state_delete(x1);
483 xfrm_state_put(x1); 491 xfrm_state_put(x1);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 0cdd9a07e0..ac87a09ba8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -7,7 +7,7 @@
7 * Kazunori MIYAZAWA @USAGI 7 * Kazunori MIYAZAWA @USAGI
8 * Kunihiro Ishiguro <kunihiro@ipinfusion.com> 8 * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
9 * IPv6 support 9 * IPv6 support
10 * 10 *
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/module.h>
@@ -88,6 +88,34 @@ static int verify_encap_tmpl(struct rtattr **xfrma)
88 return 0; 88 return 0;
89} 89}
90 90
91
92static inline int verify_sec_ctx_len(struct rtattr **xfrma)
93{
94 struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1];
95 struct xfrm_user_sec_ctx *uctx;
96 int len = 0;
97
98 if (!rt)
99 return 0;
100
101 if (rt->rta_len < sizeof(*uctx))
102 return -EINVAL;
103
104 uctx = RTA_DATA(rt);
105
106 if (uctx->ctx_len > PAGE_SIZE)
107 return -EINVAL;
108
109 len += sizeof(struct xfrm_user_sec_ctx);
110 len += uctx->ctx_len;
111
112 if (uctx->len != len)
113 return -EINVAL;
114
115 return 0;
116}
117
118
91static int verify_newsa_info(struct xfrm_usersa_info *p, 119static int verify_newsa_info(struct xfrm_usersa_info *p,
92 struct rtattr **xfrma) 120 struct rtattr **xfrma)
93{ 121{
@@ -145,6 +173,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
145 goto out; 173 goto out;
146 if ((err = verify_encap_tmpl(xfrma))) 174 if ((err = verify_encap_tmpl(xfrma)))
147 goto out; 175 goto out;
176 if ((err = verify_sec_ctx_len(xfrma)))
177 goto out;
148 178
149 err = -EINVAL; 179 err = -EINVAL;
150 switch (p->mode) { 180 switch (p->mode) {
@@ -209,6 +239,30 @@ static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_a
209 return 0; 239 return 0;
210} 240}
211 241
242
243static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp)
244{
245 struct xfrm_sec_ctx *xfrm_ctx = xp->security;
246 int len = 0;
247
248 if (xfrm_ctx) {
249 len += sizeof(struct xfrm_user_sec_ctx);
250 len += xfrm_ctx->ctx_len;
251 }
252 return len;
253}
254
255static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg)
256{
257 struct xfrm_user_sec_ctx *uctx;
258
259 if (!u_arg)
260 return 0;
261
262 uctx = RTA_DATA(u_arg);
263 return security_xfrm_state_alloc(x, uctx);
264}
265
212static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) 266static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
213{ 267{
214 memcpy(&x->id, &p->id, sizeof(x->id)); 268 memcpy(&x->id, &p->id, sizeof(x->id));
@@ -253,6 +307,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
253 if (err) 307 if (err)
254 goto error; 308 goto error;
255 309
310 if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1])))
311 goto error;
312
256 x->km.seq = p->seq; 313 x->km.seq = p->seq;
257 314
258 return x; 315 return x;
@@ -272,11 +329,11 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
272 int err; 329 int err;
273 struct km_event c; 330 struct km_event c;
274 331
275 err = verify_newsa_info(p, (struct rtattr **) xfrma); 332 err = verify_newsa_info(p, (struct rtattr **)xfrma);
276 if (err) 333 if (err)
277 return err; 334 return err;
278 335
279 x = xfrm_state_construct(p, (struct rtattr **) xfrma, &err); 336 x = xfrm_state_construct(p, (struct rtattr **)xfrma, &err);
280 if (!x) 337 if (!x)
281 return err; 338 return err;
282 339
@@ -390,6 +447,19 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
390 if (x->encap) 447 if (x->encap)
391 RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); 448 RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
392 449
450 if (x->security) {
451 int ctx_size = sizeof(struct xfrm_sec_ctx) +
452 x->security->ctx_len;
453 struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
454 struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
455
456 uctx->exttype = XFRMA_SEC_CTX;
457 uctx->len = ctx_size;
458 uctx->ctx_doi = x->security->ctx_doi;
459 uctx->ctx_alg = x->security->ctx_alg;
460 uctx->ctx_len = x->security->ctx_len;
461 memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len);
462 }
393 nlh->nlmsg_len = skb->tail - b; 463 nlh->nlmsg_len = skb->tail - b;
394out: 464out:
395 sp->this_idx++; 465 sp->this_idx++;
@@ -603,6 +673,18 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
603 return verify_policy_dir(p->dir); 673 return verify_policy_dir(p->dir);
604} 674}
605 675
676static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct rtattr **xfrma)
677{
678 struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
679 struct xfrm_user_sec_ctx *uctx;
680
681 if (!rt)
682 return 0;
683
684 uctx = RTA_DATA(rt);
685 return security_xfrm_policy_alloc(pol, uctx);
686}
687
606static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, 688static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
607 int nr) 689 int nr)
608{ 690{
@@ -681,7 +763,10 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p,
681 } 763 }
682 764
683 copy_from_user_policy(xp, p); 765 copy_from_user_policy(xp, p);
684 err = copy_from_user_tmpl(xp, xfrma); 766
767 if (!(err = copy_from_user_tmpl(xp, xfrma)))
768 err = copy_from_user_sec_ctx(xp, xfrma);
769
685 if (err) { 770 if (err) {
686 *errp = err; 771 *errp = err;
687 kfree(xp); 772 kfree(xp);
@@ -702,8 +787,11 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
702 err = verify_newpolicy_info(p); 787 err = verify_newpolicy_info(p);
703 if (err) 788 if (err)
704 return err; 789 return err;
790 err = verify_sec_ctx_len((struct rtattr **)xfrma);
791 if (err)
792 return err;
705 793
706 xp = xfrm_policy_construct(p, (struct rtattr **) xfrma, &err); 794 xp = xfrm_policy_construct(p, (struct rtattr **)xfrma, &err);
707 if (!xp) 795 if (!xp)
708 return err; 796 return err;
709 797
@@ -714,6 +802,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
714 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; 802 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
715 err = xfrm_policy_insert(p->dir, xp, excl); 803 err = xfrm_policy_insert(p->dir, xp, excl);
716 if (err) { 804 if (err) {
805 security_xfrm_policy_free(xp);
717 kfree(xp); 806 kfree(xp);
718 return err; 807 return err;
719 } 808 }
@@ -761,6 +850,27 @@ rtattr_failure:
761 return -1; 850 return -1;
762} 851}
763 852
853static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
854{
855 if (xp->security) {
856 int ctx_size = sizeof(struct xfrm_sec_ctx) +
857 xp->security->ctx_len;
858 struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
859 struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
860
861 uctx->exttype = XFRMA_SEC_CTX;
862 uctx->len = ctx_size;
863 uctx->ctx_doi = xp->security->ctx_doi;
864 uctx->ctx_alg = xp->security->ctx_alg;
865 uctx->ctx_len = xp->security->ctx_len;
866 memcpy(uctx + 1, xp->security->ctx_str, xp->security->ctx_len);
867 }
868 return 0;
869
870 rtattr_failure:
871 return -1;
872}
873
764static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) 874static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
765{ 875{
766 struct xfrm_dump_info *sp = ptr; 876 struct xfrm_dump_info *sp = ptr;
@@ -782,6 +892,8 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
782 copy_to_user_policy(xp, p, dir); 892 copy_to_user_policy(xp, p, dir);
783 if (copy_to_user_tmpl(xp, skb) < 0) 893 if (copy_to_user_tmpl(xp, skb) < 0)
784 goto nlmsg_failure; 894 goto nlmsg_failure;
895 if (copy_to_user_sec_ctx(xp, skb))
896 goto nlmsg_failure;
785 897
786 nlh->nlmsg_len = skb->tail - b; 898 nlh->nlmsg_len = skb->tail - b;
787out: 899out:
@@ -852,8 +964,25 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
852 964
853 if (p->index) 965 if (p->index)
854 xp = xfrm_policy_byid(p->dir, p->index, delete); 966 xp = xfrm_policy_byid(p->dir, p->index, delete);
855 else 967 else {
856 xp = xfrm_policy_bysel(p->dir, &p->sel, delete); 968 struct rtattr **rtattrs = (struct rtattr **)xfrma;
969 struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
970 struct xfrm_policy tmp;
971
972 err = verify_sec_ctx_len(rtattrs);
973 if (err)
974 return err;
975
976 memset(&tmp, 0, sizeof(struct xfrm_policy));
977 if (rt) {
978 struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
979
980 if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
981 return err;
982 }
983 xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, delete);
984 security_xfrm_policy_free(&tmp);
985 }
857 if (xp == NULL) 986 if (xp == NULL)
858 return -ENOENT; 987 return -ENOENT;
859 988
@@ -1224,6 +1353,8 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
1224 1353
1225 if (copy_to_user_tmpl(xp, skb) < 0) 1354 if (copy_to_user_tmpl(xp, skb) < 0)
1226 goto nlmsg_failure; 1355 goto nlmsg_failure;
1356 if (copy_to_user_sec_ctx(xp, skb))
1357 goto nlmsg_failure;
1227 1358
1228 nlh->nlmsg_len = skb->tail - b; 1359 nlh->nlmsg_len = skb->tail - b;
1229 return skb->len; 1360 return skb->len;
@@ -1241,6 +1372,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
1241 1372
1242 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); 1373 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
1243 len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire)); 1374 len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
1375 len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
1244 skb = alloc_skb(len, GFP_ATOMIC); 1376 skb = alloc_skb(len, GFP_ATOMIC);
1245 if (skb == NULL) 1377 if (skb == NULL)
1246 return -ENOMEM; 1378 return -ENOMEM;
@@ -1324,6 +1456,8 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
1324 copy_to_user_policy(xp, &upe->pol, dir); 1456 copy_to_user_policy(xp, &upe->pol, dir);
1325 if (copy_to_user_tmpl(xp, skb) < 0) 1457 if (copy_to_user_tmpl(xp, skb) < 0)
1326 goto nlmsg_failure; 1458 goto nlmsg_failure;
1459 if (copy_to_user_sec_ctx(xp, skb))
1460 goto nlmsg_failure;
1327 upe->hard = !!hard; 1461 upe->hard = !!hard;
1328 1462
1329 nlh->nlmsg_len = skb->tail - b; 1463 nlh->nlmsg_len = skb->tail - b;
@@ -1341,6 +1475,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
1341 1475
1342 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); 1476 len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
1343 len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire)); 1477 len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
1478 len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
1344 skb = alloc_skb(len, GFP_ATOMIC); 1479 skb = alloc_skb(len, GFP_ATOMIC);
1345 if (skb == NULL) 1480 if (skb == NULL)
1346 return -ENOMEM; 1481 return -ENOMEM;