[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:
parent
82453021b8
commit
b791160b5a
|
@ -331,15 +331,31 @@ static void xfrm_dst_hash_transfer(struct hlist_head *list,
|
||||||
struct hlist_head *ndsttable,
|
struct hlist_head *ndsttable,
|
||||||
unsigned int nhashmask)
|
unsigned int nhashmask)
|
||||||
{
|
{
|
||||||
struct hlist_node *entry, *tmp;
|
struct hlist_node *entry, *tmp, *entry0 = NULL;
|
||||||
struct xfrm_policy *pol;
|
struct xfrm_policy *pol;
|
||||||
|
unsigned int h0 = 0;
|
||||||
|
|
||||||
|
redo:
|
||||||
hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) {
|
hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) {
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
|
|
||||||
h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr,
|
h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr,
|
||||||
pol->family, nhashmask);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue