aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-01-16 19:52:02 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-01-23 23:25:51 -0500
commita6c7ab55dda3e16ab5a3cf6f39585aee5876ac3a (patch)
tree2ad7ed20bcf18bf1ff8b9354ec0a8f498627c1eb /net/xfrm
parent8f1adb5f27d352c776ac34648cc277d1f8199dba (diff)
[IPSEC]: Policy list disorder
The recent hashing introduced an off-by-one bug in policy list insertion. Instead of adding after the last entry with a lesser or equal priority, we're adding after the successor of that entry. This patch fixes this and also adds a warning if we detect a duplicate entry in the policy list. This should never happen due to this if clause. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index bebd40e5a62e..b7e537fe2d75 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -650,19 +650,18 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
650 struct xfrm_policy *pol; 650 struct xfrm_policy *pol;
651 struct xfrm_policy *delpol; 651 struct xfrm_policy *delpol;
652 struct hlist_head *chain; 652 struct hlist_head *chain;
653 struct hlist_node *entry, *newpos, *last; 653 struct hlist_node *entry, *newpos;
654 struct dst_entry *gc_list; 654 struct dst_entry *gc_list;
655 655
656 write_lock_bh(&xfrm_policy_lock); 656 write_lock_bh(&xfrm_policy_lock);
657 chain = policy_hash_bysel(&policy->selector, policy->family, dir); 657 chain = policy_hash_bysel(&policy->selector, policy->family, dir);
658 delpol = NULL; 658 delpol = NULL;
659 newpos = NULL; 659 newpos = NULL;
660 last = NULL;
661 hlist_for_each_entry(pol, entry, chain, bydst) { 660 hlist_for_each_entry(pol, entry, chain, bydst) {
662 if (!delpol && 661 if (pol->type == policy->type &&
663 pol->type == policy->type &&
664 !selector_cmp(&pol->selector, &policy->selector) && 662 !selector_cmp(&pol->selector, &policy->selector) &&
665 xfrm_sec_ctx_match(pol->security, policy->security)) { 663 xfrm_sec_ctx_match(pol->security, policy->security) &&
664 !WARN_ON(delpol)) {
666 if (excl) { 665 if (excl) {
667 write_unlock_bh(&xfrm_policy_lock); 666 write_unlock_bh(&xfrm_policy_lock);
668 return -EEXIST; 667 return -EEXIST;
@@ -671,17 +670,12 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
671 if (policy->priority > pol->priority) 670 if (policy->priority > pol->priority)
672 continue; 671 continue;
673 } else if (policy->priority >= pol->priority) { 672 } else if (policy->priority >= pol->priority) {
674 last = &pol->bydst; 673 newpos = &pol->bydst;
675 continue; 674 continue;
676 } 675 }
677 if (!newpos)
678 newpos = &pol->bydst;
679 if (delpol) 676 if (delpol)
680 break; 677 break;
681 last = &pol->bydst;
682 } 678 }
683 if (!newpos)
684 newpos = last;
685 if (newpos) 679 if (newpos)
686 hlist_add_after(newpos, &policy->bydst); 680 hlist_add_after(newpos, &policy->bydst);
687 else 681 else