mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
xfrm: policy: check reinserted policies match their node
validate the re-inserted policies match the lookup node. Policies that fail this test won't be returned in the candidate set. This is enabled by default for now, it should not cause noticeable reinsert slow down. Such reinserts are needed when we have to merge an existing node (e.g. for 10.0.0.0/28 because a overlapping subnet was added (e.g. 10.0.0.0/24), so whenever this happens existing policies have to be placed on the list of the new node. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
parent
9cf545ebd5
commit
e901cbc293
@ -806,10 +806,16 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
|
||||
struct xfrm_pol_inexact_node *n,
|
||||
u16 family)
|
||||
{
|
||||
unsigned int matched_s, matched_d;
|
||||
struct hlist_node *newpos = NULL;
|
||||
struct xfrm_policy *policy, *p;
|
||||
|
||||
matched_s = 0;
|
||||
matched_d = 0;
|
||||
|
||||
list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
|
||||
bool matches_s, matches_d;
|
||||
|
||||
if (!policy->bydst_reinsert)
|
||||
continue;
|
||||
|
||||
@ -827,6 +833,32 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
|
||||
hlist_add_behind(&policy->bydst, newpos);
|
||||
else
|
||||
hlist_add_head(&policy->bydst, &n->hhead);
|
||||
|
||||
/* paranoia checks follow.
|
||||
* Check that the reinserted policy matches at least
|
||||
* saddr or daddr for current node prefix.
|
||||
*
|
||||
* Matching both is fine, matching saddr in one policy
|
||||
* (but not daddr) and then matching only daddr in another
|
||||
* is a bug.
|
||||
*/
|
||||
matches_s = xfrm_policy_addr_delta(&policy->selector.saddr,
|
||||
&n->addr,
|
||||
n->prefixlen,
|
||||
family) == 0;
|
||||
matches_d = xfrm_policy_addr_delta(&policy->selector.daddr,
|
||||
&n->addr,
|
||||
n->prefixlen,
|
||||
family) == 0;
|
||||
if (matches_s && matches_d)
|
||||
continue;
|
||||
|
||||
WARN_ON_ONCE(!matches_s && !matches_d);
|
||||
if (matches_s)
|
||||
matched_s++;
|
||||
if (matches_d)
|
||||
matched_d++;
|
||||
WARN_ON_ONCE(matched_s && matched_d);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user