Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cb8a939 authored by Steffen Klassert's avatar Steffen Klassert
Browse files

xfrm: Allow inserting policies with matching mark and different priorities



We currently can not insert policies with mark and mask
such that some flows would be matched from both policies.
We make this possible when the priority of these policies
are different. If both policies match a flow, the one with
the higher priority is used.

Reported-by: default avatarEmmanuel Thierry <emmanuel.thierry@telecom-bretagne.eu>
Reported-by: default avatarRomain Kuntz <r.kuntz@ipflavors.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 8d068875
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -607,6 +607,21 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
	spin_unlock_bh(&pq->hold_queue.lock);
}

static bool xfrm_policy_mark_match(struct xfrm_policy *policy,
				   struct xfrm_policy *pol)
{
	u32 mark = policy->mark.v & policy->mark.m;

	if (policy->mark.v == pol->mark.v && policy->mark.m == pol->mark.m)
		return true;

	if ((mark & pol->mark.m) == pol->mark.v &&
	    policy->priority == pol->priority)
		return true;

	return false;
}

int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
{
	struct net *net = xp_net(policy);
@@ -614,7 +629,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
	struct xfrm_policy *delpol;
	struct hlist_head *chain;
	struct hlist_node *entry, *newpos;
	u32 mark = policy->mark.v & policy->mark.m;

	write_lock_bh(&xfrm_policy_lock);
	chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
@@ -623,7 +637,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
	hlist_for_each_entry(pol, entry, chain, bydst) {
		if (pol->type == policy->type &&
		    !selector_cmp(&pol->selector, &policy->selector) &&
		    (mark & pol->mark.m) == pol->mark.v &&
		    xfrm_policy_mark_match(policy, pol) &&
		    xfrm_sec_ctx_match(pol->security, policy->security) &&
		    !WARN_ON(delpol)) {
			if (excl) {