diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0ecb16a9a883..34a5ef8316e7 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -556,6 +556,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
| 556 | struct hlist_head *chain; | 556 | struct hlist_head *chain; |
| 557 | struct hlist_node *entry, *newpos; | 557 | struct hlist_node *entry, *newpos; |
| 558 | struct dst_entry *gc_list; | 558 | struct dst_entry *gc_list; |
| 559 | u32 mark = policy->mark.v & policy->mark.m; | ||
| 559 | 560 | ||
| 560 | write_lock_bh(&xfrm_policy_lock); | 561 | write_lock_bh(&xfrm_policy_lock); |
| 561 | chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); | 562 | chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); |
| @@ -564,6 +565,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
| 564 | hlist_for_each_entry(pol, entry, chain, bydst) { | 565 | hlist_for_each_entry(pol, entry, chain, bydst) { |
| 565 | if (pol->type == policy->type && | 566 | if (pol->type == policy->type && |
| 566 | !selector_cmp(&pol->selector, &policy->selector) && | 567 | !selector_cmp(&pol->selector, &policy->selector) && |
| 568 | (mark & pol->mark.m) == pol->mark.v && | ||
| 567 | xfrm_sec_ctx_match(pol->security, policy->security) && | 569 | xfrm_sec_ctx_match(pol->security, policy->security) && |
| 568 | !WARN_ON(delpol)) { | 570 | !WARN_ON(delpol)) { |
| 569 | if (excl) { | 571 | if (excl) { |
| @@ -635,8 +637,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
| 635 | } | 637 | } |
| 636 | EXPORT_SYMBOL(xfrm_policy_insert); | 638 | EXPORT_SYMBOL(xfrm_policy_insert); |
| 637 | 639 | ||
| 638 | struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, | 640 | struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, |
| 639 | struct xfrm_selector *sel, | 641 | int dir, struct xfrm_selector *sel, |
| 640 | struct xfrm_sec_ctx *ctx, int delete, | 642 | struct xfrm_sec_ctx *ctx, int delete, |
| 641 | int *err) | 643 | int *err) |
| 642 | { | 644 | { |
| @@ -650,6 +652,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, | |||
| 650 | ret = NULL; | 652 | ret = NULL; |
| 651 | hlist_for_each_entry(pol, entry, chain, bydst) { | 653 | hlist_for_each_entry(pol, entry, chain, bydst) { |
| 652 | if (pol->type == type && | 654 | if (pol->type == type && |
| 655 | (mark & pol->mark.m) == pol->mark.v && | ||
| 653 | !selector_cmp(sel, &pol->selector) && | 656 | !selector_cmp(sel, &pol->selector) && |
| 654 | xfrm_sec_ctx_match(ctx, pol->security)) { | 657 | xfrm_sec_ctx_match(ctx, pol->security)) { |
| 655 | xfrm_pol_hold(pol); | 658 | xfrm_pol_hold(pol); |
| @@ -676,8 +679,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, | |||
| 676 | } | 679 | } |
| 677 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); | 680 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); |
| 678 | 681 | ||
| 679 | struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, | 682 | struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, |
| 680 | int delete, int *err) | 683 | int dir, u32 id, int delete, int *err) |
| 681 | { | 684 | { |
| 682 | struct xfrm_policy *pol, *ret; | 685 | struct xfrm_policy *pol, *ret; |
| 683 | struct hlist_head *chain; | 686 | struct hlist_head *chain; |
| @@ -692,7 +695,8 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, | |||
| 692 | chain = net->xfrm.policy_byidx + idx_hash(net, id); | 695 | chain = net->xfrm.policy_byidx + idx_hash(net, id); |
| 693 | ret = NULL; | 696 | ret = NULL; |
| 694 | hlist_for_each_entry(pol, entry, chain, byidx) { | 697 | hlist_for_each_entry(pol, entry, chain, byidx) { |
| 695 | if (pol->type == type && pol->index == id) { | 698 | if (pol->type == type && pol->index == id && |
| 699 | (mark & pol->mark.m) == pol->mark.v) { | ||
| 696 | xfrm_pol_hold(pol); | 700 | xfrm_pol_hold(pol); |
| 697 | if (delete) { | 701 | if (delete) { |
| 698 | *err = security_xfrm_policy_delete( | 702 | *err = security_xfrm_policy_delete( |
| @@ -771,7 +775,8 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi | |||
| 771 | 775 | ||
| 772 | int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | 776 | int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) |
| 773 | { | 777 | { |
| 774 | int dir, err = 0; | 778 | int dir, err = 0, cnt = 0; |
| 779 | struct xfrm_policy *dp; | ||
| 775 | 780 | ||
| 776 | write_lock_bh(&xfrm_policy_lock); | 781 | write_lock_bh(&xfrm_policy_lock); |
| 777 | 782 | ||
| @@ -789,8 +794,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
| 789 | &net->xfrm.policy_inexact[dir], bydst) { | 794 | &net->xfrm.policy_inexact[dir], bydst) { |
| 790 | if (pol->type != type) | 795 | if (pol->type != type) |
| 791 | continue; | 796 | continue; |
| 792 | __xfrm_policy_unlink(pol, dir); | 797 | dp = __xfrm_policy_unlink(pol, dir); |
| 793 | write_unlock_bh(&xfrm_policy_lock); | 798 | write_unlock_bh(&xfrm_policy_lock); |
| 799 | if (dp) | ||
| 800 | cnt++; | ||
| 794 | 801 | ||
| 795 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, | 802 | xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, |
| 796 | audit_info->sessionid, | 803 | audit_info->sessionid, |
| @@ -809,8 +816,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
| 809 | bydst) { | 816 | bydst) { |
| 810 | if (pol->type != type) | 817 | if (pol->type != type) |
| 811 | continue; | 818 | continue; |
| 812 | __xfrm_policy_unlink(pol, dir); | 819 | dp = __xfrm_policy_unlink(pol, dir); |
| 813 | write_unlock_bh(&xfrm_policy_lock); | 820 | write_unlock_bh(&xfrm_policy_lock); |
| 821 | if (dp) | ||
| 822 | cnt++; | ||
| 814 | 823 | ||
| 815 | xfrm_audit_policy_delete(pol, 1, | 824 | xfrm_audit_policy_delete(pol, 1, |
| 816 | audit_info->loginuid, | 825 | audit_info->loginuid, |
| @@ -824,6 +833,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) | |||
| 824 | } | 833 | } |
| 825 | 834 | ||
| 826 | } | 835 | } |
| 836 | if (!cnt) | ||
| 837 | err = -ESRCH; | ||
| 827 | atomic_inc(&flow_cache_genid); | 838 | atomic_inc(&flow_cache_genid); |
| 828 | out: | 839 | out: |
| 829 | write_unlock_bh(&xfrm_policy_lock); | 840 | write_unlock_bh(&xfrm_policy_lock); |
| @@ -909,6 +920,7 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, | |||
| 909 | int match, ret = -ESRCH; | 920 | int match, ret = -ESRCH; |
| 910 | 921 | ||
| 911 | if (pol->family != family || | 922 | if (pol->family != family || |
| 923 | (fl->mark & pol->mark.m) != pol->mark.v || | ||
| 912 | pol->type != type) | 924 | pol->type != type) |
| 913 | return ret; | 925 | return ret; |
| 914 | 926 | ||
| @@ -1033,6 +1045,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc | |||
| 1033 | int err = 0; | 1045 | int err = 0; |
| 1034 | 1046 | ||
| 1035 | if (match) { | 1047 | if (match) { |
| 1048 | if ((sk->sk_mark & pol->mark.m) != pol->mark.v) { | ||
| 1049 | pol = NULL; | ||
| 1050 | goto out; | ||
| 1051 | } | ||
| 1036 | err = security_xfrm_policy_lookup(pol->security, | 1052 | err = security_xfrm_policy_lookup(pol->security, |
| 1037 | fl->secid, | 1053 | fl->secid, |
| 1038 | policy_to_flow_dir(dir)); | 1054 | policy_to_flow_dir(dir)); |
| @@ -1045,6 +1061,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc | |||
| 1045 | } else | 1061 | } else |
| 1046 | pol = NULL; | 1062 | pol = NULL; |
| 1047 | } | 1063 | } |
| 1064 | out: | ||
| 1048 | read_unlock_bh(&xfrm_policy_lock); | 1065 | read_unlock_bh(&xfrm_policy_lock); |
| 1049 | return pol; | 1066 | return pol; |
| 1050 | } | 1067 | } |
| @@ -1137,6 +1154,7 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) | |||
| 1137 | } | 1154 | } |
| 1138 | newp->lft = old->lft; | 1155 | newp->lft = old->lft; |
| 1139 | newp->curlft = old->curlft; | 1156 | newp->curlft = old->curlft; |
| 1157 | newp->mark = old->mark; | ||
| 1140 | newp->action = old->action; | 1158 | newp->action = old->action; |
| 1141 | newp->flags = old->flags; | 1159 | newp->flags = old->flags; |
| 1142 | newp->xfrm_nr = old->xfrm_nr; | 1160 | newp->xfrm_nr = old->xfrm_nr; |
| @@ -2045,8 +2063,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
| 2045 | int res; | 2063 | int res; |
| 2046 | 2064 | ||
| 2047 | if (xfrm_decode_session(skb, &fl, family) < 0) { | 2065 | if (xfrm_decode_session(skb, &fl, family) < 0) { |
| 2048 | /* XXX: we should have something like FWDHDRERROR here. */ | 2066 | XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR); |
| 2049 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); | ||
| 2050 | return 0; | 2067 | return 0; |
| 2051 | } | 2068 | } |
| 2052 | 2069 | ||
| @@ -2421,19 +2438,19 @@ static int __net_init xfrm_statistics_init(struct net *net) | |||
| 2421 | { | 2438 | { |
| 2422 | int rv; | 2439 | int rv; |
| 2423 | 2440 | ||
| 2424 | if (snmp_mib_init((void **)net->mib.xfrm_statistics, | 2441 | if (snmp_mib_init((void __percpu **)net->mib.xfrm_statistics, |
| 2425 | sizeof(struct linux_xfrm_mib)) < 0) | 2442 | sizeof(struct linux_xfrm_mib)) < 0) |
| 2426 | return -ENOMEM; | 2443 | return -ENOMEM; |
| 2427 | rv = xfrm_proc_init(net); | 2444 | rv = xfrm_proc_init(net); |
| 2428 | if (rv < 0) | 2445 | if (rv < 0) |
| 2429 | snmp_mib_free((void **)net->mib.xfrm_statistics); | 2446 | snmp_mib_free((void __percpu **)net->mib.xfrm_statistics); |
| 2430 | return rv; | 2447 | return rv; |
| 2431 | } | 2448 | } |
| 2432 | 2449 | ||
| 2433 | static void xfrm_statistics_fini(struct net *net) | 2450 | static void xfrm_statistics_fini(struct net *net) |
| 2434 | { | 2451 | { |
| 2435 | xfrm_proc_fini(net); | 2452 | xfrm_proc_fini(net); |
| 2436 | snmp_mib_free((void **)net->mib.xfrm_statistics); | 2453 | snmp_mib_free((void __percpu **)net->mib.xfrm_statistics); |
| 2437 | } | 2454 | } |
| 2438 | #else | 2455 | #else |
| 2439 | static int __net_init xfrm_statistics_init(struct net *net) | 2456 | static int __net_init xfrm_statistics_init(struct net *net) |
