|
@@ -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) {
|