On Sun, May 25, 2003 at 09:04:23PM -0700, David S. Miller wrote: > > Again, please move the policy comparisons AFTER the selector > comparison... Alright, here is the updated patch which forbids the existence of two policies with the same selector. -- Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/net/xfrm/xfrm_policy.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_policy.c,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 xfrm_policy.c --- kernel-source-2.5/net/xfrm/xfrm_policy.c 4 May 2003 23:53:29 -0000 1.1.1.2 +++ kernel-source-2.5/net/xfrm/xfrm_policy.c 26 May 2003 08:52:11 -0000 @@ -381,22 +381,34 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) { struct xfrm_policy *pol, **p; + struct xfrm_policy *delpol = NULL; + struct xfrm_policy **newpos = NULL; write_lock_bh(&xfrm_policy_lock); for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { - if (memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) { + if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) { if (excl) { write_unlock_bh(&xfrm_policy_lock); return -EEXIST; } + *p = pol->next; + delpol = pol; + if (policy->priority > pol->priority) + continue; + } else if (policy->priority >= pol->priority) + continue; + if (!newpos) + newpos = p; + if (delpol) break; - } } + if (newpos) + p = newpos; atomic_inc(&policy->refcnt); - policy->next = pol ? pol->next : NULL; + policy->next = *p; *p = policy; xfrm_policy_genid++; - policy->index = pol ? pol->index : xfrm_gen_index(dir); + policy->index = delpol ? delpol->index : xfrm_gen_index(dir); policy->curlft.add_time = (unsigned long)xtime.tv_sec; policy->curlft.use_time = 0; if (policy->lft.hard_add_expires_seconds && @@ -404,10 +416,10 @@ atomic_inc(&policy->refcnt); write_unlock_bh(&xfrm_policy_lock); - if (pol) { - atomic_dec(&pol->refcnt); - xfrm_policy_kill(pol); - xfrm_pol_put(pol); + if (delpol) { + atomic_dec(&delpol->refcnt); + xfrm_policy_kill(delpol); + xfrm_pol_put(delpol); } return 0; }