[XFRM]: Fix ordering issue in xfrm_dst_hash_transfer().

Keep ordering of policy entries with same selector in
xfrm_dst_hash_transfer().

Issue should not appear in usual cases because multiple policy entries
with same selector are basically not allowed so far.  Bug was pointed
out by Sebastien Decugis <sdecugis@hongo.wide.ad.jp>.

We could convert bydst from hlist to list and use list_add_tail()
instead.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Acked-by: Sebastien Decugis <sdecugis@hongo.wide.ad.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
YOSHIFUJI Hideaki 2008-02-17 23:29:30 -08:00 committed by David S. Miller
parent 82453021b8
commit b791160b5a
1 changed files with 18 additions and 2 deletions

View File

@ -331,15 +331,31 @@ static void xfrm_dst_hash_transfer(struct hlist_head *list,
struct hlist_head *ndsttable,
unsigned int nhashmask)
{
struct hlist_node *entry, *tmp;
struct hlist_node *entry, *tmp, *entry0 = NULL;
struct xfrm_policy *pol;
unsigned int h0 = 0;
redo:
hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) {
unsigned int h;
h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr,
pol->family, nhashmask);
hlist_add_head(&pol->bydst, ndsttable+h);
if (!entry0) {
hlist_del(entry);
hlist_add_head(&pol->bydst, ndsttable+h);
h0 = h;
} else {
if (h != h0)
continue;
hlist_del(entry);
hlist_add_after(entry0, &pol->bydst);
}
entry0 = entry;
}
if (!hlist_empty(list)) {
entry0 = NULL;
goto redo;
}
}