Thread (6 messages) 6 messages, 4 authors, 2020-07-07

Re: [PATCH ipsec] xfrm: state: match with both mark and mask on user interfaces

From: Xin Long <lucien.xin@gmail.com>
Date: 2020-07-06 08:24:13

Hi, Tobias

Sorry for late.

On Tue, Jun 30, 2020 at 5:08 PM Tobias Brunner [off-list ref] wrote:
Hi Xin,
quoted
Similar to commit 4f47e8ab6ab79 ("xfrm: policy: match with both mark and
mask on user interfaces"), this patch is to match both mark and mask for
state on these user interfaces:

  xfrm_state_lookup_byaddr_user
  xfrm_state_lookup_user
  xfrm_state_update
  xfrm_state_find
  xfrm_state_add
      __xfrm_state_lookup_byaddr(struct xfrm_mark)
      __xfrm_state_lookup(struct xfrm_mark)
  xfrm_find_acq_byseq
  xfrm_stateonly_find

          mark.v == x->mark.v && mark.m == x->mark.m
I generally agree with matching marks/masks exactly for operations from
userland, and it doesn't introduce any issues in our test suite.
However, xfrm_state_find() is used to find an outbound state based on
the templates in a policy and the marks on both, so it's not directly
userland-facing.  Before this change, the mask configured on the state
was a applied to the policy's mark/mask and then compared to the state's
mark.  Now, the mark and mask both must match exactly:
Good catch.
quoted
@@ -1051,7 +1061,6 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
      int acquire_in_progress = 0;
      int error = 0;
      struct xfrm_state *best = NULL;
-     u32 mark = pol->mark.v & pol->mark.m;
      unsigned short encap_family = tmpl->encap_family;
      unsigned int sequence;
      struct km_event c;
@@ -1065,7 +1074,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
      hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h, bydst) {
              if (x->props.family == encap_family &&
                  x->props.reqid == tmpl->reqid &&
-                 (mark & x->mark.m) == x->mark.v &&
+                 (pol->mark.v == x->mark.v && pol->mark.m == x->mark.m) &&
                  x->if_id == if_id &&
                  !(x->props.flags & XFRM_STATE_WILDRECV) &&
                  xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
@@ -1082,7 +1091,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
      hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h_wildcard, bydst) {
              if (x->props.family == encap_family &&
                  x->props.reqid == tmpl->reqid &&
-                 (mark & x->mark.m) == x->mark.v &&
+                 (pol->mark.v == x->mark.v && pol->mark.m == x->mark.m) &&
                  x->if_id == if_id &&
                  !(x->props.flags & XFRM_STATE_WILDRECV) &&
                  xfrm_addr_equal(&x->id.daddr, daddr, encap_family) &&
While this should usually not be a problem for strongSwan, as we set the
same mark/value on both states and corresponding policies (although the
latter can be disabled as users may want to install policies themselves
or via another daemon e.g. for MIPv6), it might be a limitation for some
use cases.  The current code allows sharing states with multiple
policies whose mark/mask doesn't match exactly (i.e. depended on the
masks of both).  I wonder if anybody uses it like this, and how others
think about it.
IMHO, the non-exact match "(mark & x->mark.m) == x->mark.v" should be only
for packet flow. "sharing states with multiple policies" should not be the
purpose of xfrm_mark. (Add Jamal to the CC list)

"(((pol->mark.v & pol->mark.m) & x->mark.m) == x->mark.v)" is just strange.
We could do either:
 (pol->mark.v == x->mark.v && pol->mark.m == x->mark.m), like this patch.
Or use fl->flowi_mark in xfrm_state_find():
 (fl->flowi_mark & x->mark.m) == x->mark.v)

The 1st one will require userland to configure policy and state with the
same xfrm_mark, like strongswan.

The 2nd one will match state with tx packet flow's mark, it's more like
rx packet flow path.

But you're right, either of these may cause slight differences, let's see
how other userland cases use it. (also Add Libreswan's developer, Paul Wouters)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help