Commit 0b91fda3 authored by Paul Chaignon's avatar Paul Chaignon Committed by Steffen Klassert
Browse files

xfrm: Sanitize marks before insert



Prior to this patch, the mark is sanitized (applying the state's mask to
the state's value) only on inserts when checking if a conflicting XFRM
state or policy exists.

We discovered in Cilium that this same sanitization does not occur
in the hot-path __xfrm_state_lookup. In the hot-path, the sk_buff's mark
is simply compared to the state's value:

    if ((mark & x->mark.m) != x->mark.v)
        continue;

Therefore, users can define unsanitized marks (ex. 0xf42/0xf00) which will
never match any packet.

This commit updates __xfrm_state_insert and xfrm_policy_insert to store
the sanitized marks, thus removing this footgun.

This has the side effect of changing the ip output, as the
returned mark will have the mask applied to it when printed.

Fixes: 3d6acfa7 ("xfrm: SA lookups with mark")
Signed-off-by: default avatarPaul Chaignon <paul.chaignon@gmail.com>
Signed-off-by: default avatarLouis DeLosSantos <louis.delos.devel@gmail.com>
Co-developed-by: default avatarLouis DeLosSantos <louis.delos.devel@gmail.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 417fae2c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1581,6 +1581,9 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
	struct xfrm_policy *delpol;
	struct hlist_head *chain;

	/* Sanitize mark before store */
	policy->mark.v &= policy->mark.m;

	spin_lock_bh(&net->xfrm.xfrm_policy_lock);
	chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
	if (chain)
+3 −0
Original line number Diff line number Diff line
@@ -1718,6 +1718,9 @@ static void __xfrm_state_insert(struct xfrm_state *x)

	list_add(&x->km.all, &net->xfrm.state_all);

	/* Sanitize mark before store */
	x->mark.v &= x->mark.m;

	h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr,
			  x->props.reqid, x->props.family);
	XFRM_STATE_INSERT(bydst, &x->bydst, net->xfrm.state_bydst + h,