aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c88
1 files changed, 54 insertions, 34 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d19e274b9c4a..64a447375fdb 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>
@@ -256,6 +256,7 @@ void __xfrm_policy_destroy(struct xfrm_policy *policy)
256 if (del_timer(&policy->timer)) 256 if (del_timer(&policy->timer))
257 BUG(); 257 BUG();
258 258
259 security_xfrm_policy_free(policy);
259 kfree(policy); 260 kfree(policy);
260} 261}
261EXPORT_SYMBOL(__xfrm_policy_destroy); 262EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -350,7 +351,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
350 351
351 write_lock_bh(&xfrm_policy_lock); 352 write_lock_bh(&xfrm_policy_lock);
352 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { 353 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
353 if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) { 354 if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 &&
355 xfrm_sec_ctx_match(pol->security, policy->security)) {
354 if (excl) { 356 if (excl) {
355 write_unlock_bh(&xfrm_policy_lock); 357 write_unlock_bh(&xfrm_policy_lock);
356 return -EEXIST; 358 return -EEXIST;
@@ -416,14 +418,15 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
416} 418}
417EXPORT_SYMBOL(xfrm_policy_insert); 419EXPORT_SYMBOL(xfrm_policy_insert);
418 420
419struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, 421struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
420 int delete) 422 struct xfrm_sec_ctx *ctx, int delete)
421{ 423{
422 struct xfrm_policy *pol, **p; 424 struct xfrm_policy *pol, **p;
423 425
424 write_lock_bh(&xfrm_policy_lock); 426 write_lock_bh(&xfrm_policy_lock);
425 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { 427 for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
426 if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) { 428 if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) &&
429 (xfrm_sec_ctx_match(ctx, pol->security))) {
427 xfrm_pol_hold(pol); 430 xfrm_pol_hold(pol);
428 if (delete) 431 if (delete)
429 *p = pol->next; 432 *p = pol->next;
@@ -438,7 +441,7 @@ struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
438 } 441 }
439 return pol; 442 return pol;
440} 443}
441EXPORT_SYMBOL(xfrm_policy_bysel); 444EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
442 445
443struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) 446struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
444{ 447{
@@ -519,7 +522,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
519 522
520/* Find policy to apply to this flow. */ 523/* Find policy to apply to this flow. */
521 524
522static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, 525static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir,
523 void **objp, atomic_t **obj_refp) 526 void **objp, atomic_t **obj_refp)
524{ 527{
525 struct xfrm_policy *pol; 528 struct xfrm_policy *pol;
@@ -533,9 +536,12 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
533 continue; 536 continue;
534 537
535 match = xfrm_selector_match(sel, fl, family); 538 match = xfrm_selector_match(sel, fl, family);
539
536 if (match) { 540 if (match) {
537 xfrm_pol_hold(pol); 541 if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) {
538 break; 542 xfrm_pol_hold(pol);
543 break;
544 }
539 } 545 }
540 } 546 }
541 read_unlock_bh(&xfrm_policy_lock); 547 read_unlock_bh(&xfrm_policy_lock);
@@ -543,15 +549,37 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
543 *obj_refp = &pol->refcnt; 549 *obj_refp = &pol->refcnt;
544} 550}
545 551
546static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl) 552static inline int policy_to_flow_dir(int dir)
553{
554 if (XFRM_POLICY_IN == FLOW_DIR_IN &&
555 XFRM_POLICY_OUT == FLOW_DIR_OUT &&
556 XFRM_POLICY_FWD == FLOW_DIR_FWD)
557 return dir;
558 switch (dir) {
559 default:
560 case XFRM_POLICY_IN:
561 return FLOW_DIR_IN;
562 case XFRM_POLICY_OUT:
563 return FLOW_DIR_OUT;
564 case XFRM_POLICY_FWD:
565 return FLOW_DIR_FWD;
566 };
567}
568
569static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid)
547{ 570{
548 struct xfrm_policy *pol; 571 struct xfrm_policy *pol;
549 572
550 read_lock_bh(&xfrm_policy_lock); 573 read_lock_bh(&xfrm_policy_lock);
551 if ((pol = sk->sk_policy[dir]) != NULL) { 574 if ((pol = sk->sk_policy[dir]) != NULL) {
552 int match = xfrm_selector_match(&pol->selector, fl, 575 int match = xfrm_selector_match(&pol->selector, fl,
553 sk->sk_family); 576 sk->sk_family);
577 int err = 0;
578
554 if (match) 579 if (match)
580 err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir));
581
582 if (match && !err)
555 xfrm_pol_hold(pol); 583 xfrm_pol_hold(pol);
556 else 584 else
557 pol = NULL; 585 pol = NULL;
@@ -624,6 +652,10 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
624 652
625 if (newp) { 653 if (newp) {
626 newp->selector = old->selector; 654 newp->selector = old->selector;
655 if (security_xfrm_policy_clone(old, newp)) {
656 kfree(newp);
657 return NULL; /* ENOMEM */
658 }
627 newp->lft = old->lft; 659 newp->lft = old->lft;
628 newp->curlft = old->curlft; 660 newp->curlft = old->curlft;
629 newp->action = old->action; 661 newp->action = old->action;
@@ -735,22 +767,6 @@ xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
735 return err; 767 return err;
736} 768}
737 769
738static inline int policy_to_flow_dir(int dir)
739{
740 if (XFRM_POLICY_IN == FLOW_DIR_IN &&
741 XFRM_POLICY_OUT == FLOW_DIR_OUT &&
742 XFRM_POLICY_FWD == FLOW_DIR_FWD)
743 return dir;
744 switch (dir) {
745 default:
746 case XFRM_POLICY_IN:
747 return FLOW_DIR_IN;
748 case XFRM_POLICY_OUT:
749 return FLOW_DIR_OUT;
750 case XFRM_POLICY_FWD:
751 return FLOW_DIR_FWD;
752 };
753}
754 770
755static int stale_bundle(struct dst_entry *dst); 771static int stale_bundle(struct dst_entry *dst);
756 772
@@ -769,19 +785,20 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
769 int err; 785 int err;
770 u32 genid; 786 u32 genid;
771 u16 family = dst_orig->ops->family; 787 u16 family = dst_orig->ops->family;
788 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
789 u32 sk_sid = security_sk_sid(sk, fl, dir);
772restart: 790restart:
773 genid = atomic_read(&flow_cache_genid); 791 genid = atomic_read(&flow_cache_genid);
774 policy = NULL; 792 policy = NULL;
775 if (sk && sk->sk_policy[1]) 793 if (sk && sk->sk_policy[1])
776 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); 794 policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid);
777 795
778 if (!policy) { 796 if (!policy) {
779 /* To accelerate a bit... */ 797 /* To accelerate a bit... */
780 if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) 798 if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
781 return 0; 799 return 0;
782 800
783 policy = flow_cache_lookup(fl, family, 801 policy = flow_cache_lookup(fl, sk_sid, family, dir,
784 policy_to_flow_dir(XFRM_POLICY_OUT),
785 xfrm_policy_lookup); 802 xfrm_policy_lookup);
786 } 803 }
787 804
@@ -962,16 +979,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
962{ 979{
963 struct xfrm_policy *pol; 980 struct xfrm_policy *pol;
964 struct flowi fl; 981 struct flowi fl;
982 u8 fl_dir = policy_to_flow_dir(dir);
983 u32 sk_sid;
965 984
966 if (_decode_session(skb, &fl, family) < 0) 985 if (_decode_session(skb, &fl, family) < 0)
967 return 0; 986 return 0;
968 987
988 sk_sid = security_sk_sid(sk, &fl, fl_dir);
989
969 /* First, check used SA against their selectors. */ 990 /* First, check used SA against their selectors. */
970 if (skb->sp) { 991 if (skb->sp) {
971 int i; 992 int i;
972 993
973 for (i=skb->sp->len-1; i>=0; i--) { 994 for (i=skb->sp->len-1; i>=0; i--) {
974 struct sec_decap_state *xvec = &(skb->sp->x[i]); 995 struct sec_decap_state *xvec = &(skb->sp->x[i]);
975 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) 996 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
976 return 0; 997 return 0;
977 998
@@ -986,11 +1007,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
986 1007
987 pol = NULL; 1008 pol = NULL;
988 if (sk && sk->sk_policy[dir]) 1009 if (sk && sk->sk_policy[dir])
989 pol = xfrm_sk_policy_lookup(sk, dir, &fl); 1010 pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid);
990 1011
991 if (!pol) 1012 if (!pol)
992 pol = flow_cache_lookup(&fl, family, 1013 pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir,
993 policy_to_flow_dir(dir),
994 xfrm_policy_lookup); 1014 xfrm_policy_lookup);
995 1015
996 if (!pol) 1016 if (!pol)