* [PATCH v1 0/2] Fix issues in xfrm_migrate
@ 2021-12-23 0:45 Yan Yan
2021-12-23 0:45 ` [PATCH v1 1/2] xfrm: Check if_id " Yan Yan
2021-12-23 0:45 ` [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes Yan Yan
0 siblings, 2 replies; 8+ messages in thread
From: Yan Yan @ 2021-12-23 0:45 UTC (permalink / raw)
To: steffen.klassert
Cc: herbert, davem, netdev, nharold, benedictwong, maze, lorenzo,
Yan Yan
This patch series include two patches to fix two issues in xfrm_migrate.
PATCH 1/2 enables distinguishing SAs and SPs based on if_id during the
xfrm_migrate flow. It fixes the problem that when there are multiple
existing SPs with the same direction, the same xfrm_selector and
different endpoint addresses, xfrm_migrate might fail.
PATCH 2/2 enables xfrm_migrate to handle address family change by
breaking the original xfrm_state_clone method into two steps so as to
update the props.family before running xfrm_init_state.
Yan Yan (2):
xfrm: Check if_id in xfrm_migrate
xfrm: Fix xfrm migrate issues when address family changes
include/net/xfrm.h | 5 +++--
net/xfrm/xfrm_policy.c | 14 ++++++++------
net/xfrm/xfrm_state.c | 38 +++++++++++++++++++++++++++-----------
net/xfrm/xfrm_user.c | 6 +++++-
4 files changed, 43 insertions(+), 20 deletions(-)
--
2.34.1.307.g9b7440fafd-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 1/2] xfrm: Check if_id in xfrm_migrate
2021-12-23 0:45 [PATCH v1 0/2] Fix issues in xfrm_migrate Yan Yan
@ 2021-12-23 0:45 ` Yan Yan
2021-12-25 18:30 ` kernel test robot
2021-12-23 0:45 ` [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes Yan Yan
1 sibling, 1 reply; 8+ messages in thread
From: Yan Yan @ 2021-12-23 0:45 UTC (permalink / raw)
To: steffen.klassert
Cc: herbert, davem, netdev, nharold, benedictwong, maze, lorenzo,
Yan Yan
This patch enables distinguishing SAs and SPs based on if_id during
the xfrm_migrate flow. This ensures support for xfrm interfaces
throughout the SA/SP lifecycle.
When there are multiple existing SPs with the same direction,
the same xfrm_selector and different endpoint addresses,
xfrm_migrate might fail with ENODATA.
Specifically, the code path for performing xfrm_migrate is:
Stage 1: find policy to migrate with
xfrm_migrate_policy_find(sel, dir, type, net)
Stage 2: find and update state(s) with
xfrm_migrate_state_find(mp, net)
Stage 3: update endpoint address(es) of template(s) with
xfrm_policy_migrate(pol, m, num_migrate)
Currently "Stage 1" always returns the first xfrm_policy that
matches, and "Stage 3" looks for the xfrm_tmpl that matches the
old endpoint address. Thus if there are multiple xfrm_policy
with same selector, direction, type and net, "Stage 1" might
rertun a wrong xfrm_policy and "Stage 3" will fail with ENODATA
because it cannot find a xfrm_tmpl with the matching endpoint
address.
The fix is to allow userspace to pass an if_id and add if_id
to the matching rule in Stage 1 and Stage 2 since if_id is a
unique ID for xfrm_policy and xfrm_state. For compatibility,
if_id will only be checked if the attribute is set.
Tested with additions to Android's kernel unit test suite:
https://android-review.googlesource.com/c/kernel/tests/+/1668886
Signed-off-by: Yan Yan <evitayan@google.com>
---
include/net/xfrm.h | 5 +++--
net/xfrm/xfrm_policy.c | 14 ++++++++------
net/xfrm/xfrm_state.c | 7 ++++++-
net/xfrm/xfrm_user.c | 6 +++++-
4 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2308210793a0..4fdd0c44b705 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1675,14 +1675,15 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap);
-struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
+struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
+ u32 if_id);
struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
struct xfrm_migrate *m,
struct xfrm_encap_tmpl *encap);
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_migrate *m, int num_bundles,
struct xfrm_kmaddress *k, struct net *net,
- struct xfrm_encap_tmpl *encap);
+ struct xfrm_encap_tmpl *encap, u32 if_id);
#endif
int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1a06585022ab..cd656b4ec5b9 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -4235,7 +4235,7 @@ static bool xfrm_migrate_selector_match(const struct xfrm_selector *sel_cmp,
}
static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *sel,
- u8 dir, u8 type, struct net *net)
+ u8 dir, u8 type, struct net *net, u32 if_id)
{
struct xfrm_policy *pol, *ret = NULL;
struct hlist_head *chain;
@@ -4244,7 +4244,8 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
chain = policy_hash_direct(net, &sel->daddr, &sel->saddr, sel->family, dir);
hlist_for_each_entry(pol, chain, bydst) {
- if (xfrm_migrate_selector_match(sel, &pol->selector) &&
+ if ((if_id == 0 || pol->if_id == if_id) &&
+ xfrm_migrate_selector_match(sel, &pol->selector) &&
pol->type == type) {
ret = pol;
priority = ret->priority;
@@ -4256,7 +4257,8 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
if ((pol->priority >= priority) && ret)
break;
- if (xfrm_migrate_selector_match(sel, &pol->selector) &&
+ if ((if_id == 0 || pol->if_id == if_id) &&
+ xfrm_migrate_selector_match(sel, &pol->selector) &&
pol->type == type) {
ret = pol;
break;
@@ -4372,7 +4374,7 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_migrate *m, int num_migrate,
struct xfrm_kmaddress *k, struct net *net,
- struct xfrm_encap_tmpl *encap)
+ struct xfrm_encap_tmpl *encap, u32 if_id)
{
int i, err, nx_cur = 0, nx_new = 0;
struct xfrm_policy *pol = NULL;
@@ -4391,14 +4393,14 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
}
/* Stage 1 - find policy */
- if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) {
+ if ((pol = xfrm_migrate_policy_find(sel, dir, type, net, if_id)) == NULL) {
err = -ENOENT;
goto out;
}
/* Stage 2 - find and update state(s) */
for (i = 0, mp = m; i < num_migrate; i++, mp++) {
- if ((x = xfrm_migrate_state_find(mp, net))) {
+ if (x = xfrm_migrate_state_find(mp, net, if_id)) {
x_cur[nx_cur] = x;
nx_cur++;
xc = xfrm_state_migrate(x, mp, encap);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a2f4001221d1..74d4283ed282 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1602,7 +1602,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
return NULL;
}
-struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
+struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
+ u32 if_id)
{
unsigned int h;
struct xfrm_state *x = NULL;
@@ -1618,6 +1619,8 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
continue;
if (m->reqid && x->props.reqid != m->reqid)
continue;
+ if (if_id != 0 && x->if_id != if_id)
+ continue;
if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
m->old_family) ||
!xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
@@ -1633,6 +1636,8 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
if (x->props.mode != m->mode ||
x->id.proto != m->proto)
continue;
+ if (if_id != 0 && x->if_id != if_id)
+ continue;
if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
m->old_family) ||
!xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 7c36cc1f3d79..8cbbe8107543 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2579,6 +2579,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
int n = 0;
struct net *net = sock_net(skb->sk);
struct xfrm_encap_tmpl *encap = NULL;
+ u32 if_id = 0;
if (attrs[XFRMA_MIGRATE] == NULL)
return -EINVAL;
@@ -2603,7 +2604,10 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
return -ENOMEM;
}
- err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap);
+ if (attrs[XFRMA_IF_ID])
+ if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
+
+ err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap, if_id);
kfree(encap);
--
2.34.1.307.g9b7440fafd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes
2021-12-23 0:45 [PATCH v1 0/2] Fix issues in xfrm_migrate Yan Yan
2021-12-23 0:45 ` [PATCH v1 1/2] xfrm: Check if_id " Yan Yan
@ 2021-12-23 0:45 ` Yan Yan
2021-12-26 2:18 ` kernel test robot
1 sibling, 1 reply; 8+ messages in thread
From: Yan Yan @ 2021-12-23 0:45 UTC (permalink / raw)
To: steffen.klassert
Cc: herbert, davem, netdev, nharold, benedictwong, maze, lorenzo,
Yan Yan
xfrm_migrate cannot handle address family change of an xfrm_state.
The symptons are the xfrm_state will be migrated to a wrong address,
and sending as well as receiving packets wil be broken.
This commit fixes it by breaking the original xfrm_state_clone
method into two steps so as to update the props.family before
running xfrm_init_state. As the result, xfrm_state's inner mode,
outer mode, type and IP header length in xfrm_state_migrate can
be updated with the new address family.
Tested with additions to Android's kernel unit test suite:
https://android-review.googlesource.com/c/kernel/tests/+/1885354
Signed-off-by: Yan Yan <evitayan@google.com>
---
net/xfrm/xfrm_state.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 74d4283ed282..56a3530f1b67 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1503,7 +1503,7 @@ static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *secu
return 0;
}
-static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+static struct xfrm_state *xfrm_state_clone1(struct xfrm_state *orig,
struct xfrm_encap_tmpl *encap)
{
struct net *net = xs_net(orig);
@@ -1578,8 +1578,20 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
memcpy(&x->mark, &orig->mark, sizeof(x->mark));
memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
- if (xfrm_init_state(x) < 0)
- goto error;
+ return x;
+
+ error:
+ xfrm_state_put(x);
+out:
+ return NULL;
+}
+
+static int *xfrm_state_clone2(struct xfrm_state *orig,
+ struct xfrm_state *x)
+{
+ int err = xfrm_init_state(x);
+ if (err < 0)
+ return err;
x->props.flags = orig->props.flags;
x->props.extra_flags = orig->props.extra_flags;
@@ -1594,12 +1606,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
x->replay = orig->replay;
x->preplay = orig->preplay;
- return x;
-
- error:
- xfrm_state_put(x);
-out:
- return NULL;
+ return 0;
}
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
@@ -1660,10 +1667,14 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
{
struct xfrm_state *xc;
- xc = xfrm_state_clone(x, encap);
+ xc = xfrm_state_clone1(x, encap);
if (!xc)
return NULL;
+ xc->props.family = m->new_family;
+ if (xfrm_state_clone2(x, xc) < 0)
+ goto error;
+
memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
--
2.34.1.307.g9b7440fafd-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1 1/2] xfrm: Check if_id in xfrm_migrate
2021-12-23 0:45 ` [PATCH v1 1/2] xfrm: Check if_id " Yan Yan
@ 2021-12-25 18:30 ` kernel test robot
0 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2021-12-25 18:30 UTC (permalink / raw)
To: Yan Yan, steffen.klassert
Cc: kbuild-all, herbert, davem, netdev, nharold, benedictwong, maze,
lorenzo, Yan Yan
Hi Yan,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on klassert-ipsec-next/master]
[also build test ERROR on klassert-ipsec/master net-next/master net/master v5.16-rc6 next-20211224]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Yan-Yan/Fix-issues-in-xfrm_migrate/20211223-084725
base: https://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git master
config: x86_64-rhel-8.3 (https://download.01.org/0day-ci/archive/20211226/202112260218.oyI4rj2f-lkp@intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
# https://github.com/0day-ci/linux/commit/a1b1a05814d4ac913aa4af753da7e116a3d58342
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Yan-Yan/Fix-issues-in-xfrm_migrate/20211223-084725
git checkout a1b1a05814d4ac913aa4af753da7e116a3d58342
# save the config file to linux build tree
mkdir build_dir
make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpio/ net/key/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
net/key/af_key.c: In function 'pfkey_migrate':
>> net/key/af_key.c:2625:9: error: too few arguments to function 'xfrm_migrate'
2625 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
| ^~~~~~~~~~~~
In file included from net/key/af_key.c:28:
include/net/xfrm.h:1683:5: note: declared here
1683 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
| ^~~~~~~~~~~~
vim +/xfrm_migrate +2625 net/key/af_key.c
08de61beab8a21 Shinta Sugimoto 2007-02-08 2539
08de61beab8a21 Shinta Sugimoto 2007-02-08 2540 static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
4c93fbb0626080 David S. Miller 2011-02-25 2541 const struct sadb_msg *hdr, void * const *ext_hdrs)
08de61beab8a21 Shinta Sugimoto 2007-02-08 2542 {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2543 int i, len, ret, err = -EINVAL;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2544 u8 dir;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2545 struct sadb_address *sa;
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2546 struct sadb_x_kmaddress *kma;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2547 struct sadb_x_policy *pol;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2548 struct sadb_x_ipsecrequest *rq;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2549 struct xfrm_selector sel;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2550 struct xfrm_migrate m[XFRM_MAX_DEPTH];
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2551 struct xfrm_kmaddress k;
8d549c4f5d92d8 Fan Du 2013-11-07 2552 struct net *net = sock_net(sk);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2553
08de61beab8a21 Shinta Sugimoto 2007-02-08 2554 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1],
08de61beab8a21 Shinta Sugimoto 2007-02-08 2555 ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) ||
08de61beab8a21 Shinta Sugimoto 2007-02-08 2556 !ext_hdrs[SADB_X_EXT_POLICY - 1]) {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2557 err = -EINVAL;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2558 goto out;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2559 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2560
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2561 kma = ext_hdrs[SADB_X_EXT_KMADDRESS - 1];
08de61beab8a21 Shinta Sugimoto 2007-02-08 2562 pol = ext_hdrs[SADB_X_EXT_POLICY - 1];
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2563
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2564 if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2565 err = -EINVAL;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2566 goto out;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2567 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2568
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2569 if (kma) {
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2570 /* convert sadb_x_kmaddress to xfrm_kmaddress */
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2571 k.reserved = kma->sadb_x_kmaddress_reserved;
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2572 ret = parse_sockaddr_pair((struct sockaddr *)(kma + 1),
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2573 8*(kma->sadb_x_kmaddress_len) - sizeof(*kma),
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2574 &k.local, &k.remote, &k.family);
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2575 if (ret < 0) {
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2576 err = ret;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2577 goto out;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2578 }
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 2579 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2580
08de61beab8a21 Shinta Sugimoto 2007-02-08 2581 dir = pol->sadb_x_policy_dir - 1;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2582 memset(&sel, 0, sizeof(sel));
08de61beab8a21 Shinta Sugimoto 2007-02-08 2583
08de61beab8a21 Shinta Sugimoto 2007-02-08 2584 /* set source address info of selector */
08de61beab8a21 Shinta Sugimoto 2007-02-08 2585 sa = ext_hdrs[SADB_EXT_ADDRESS_SRC - 1];
08de61beab8a21 Shinta Sugimoto 2007-02-08 2586 sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2587 sel.prefixlen_s = sa->sadb_address_prefixlen;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2588 sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2589 sel.sport = ((struct sockaddr_in *)(sa + 1))->sin_port;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2590 if (sel.sport)
582ee43dad8e41 Al Viro 2007-07-26 2591 sel.sport_mask = htons(0xffff);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2592
08de61beab8a21 Shinta Sugimoto 2007-02-08 2593 /* set destination address info of selector */
47162c0b7e26ef Himangi Saraogi 2014-05-30 2594 sa = ext_hdrs[SADB_EXT_ADDRESS_DST - 1];
08de61beab8a21 Shinta Sugimoto 2007-02-08 2595 pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2596 sel.prefixlen_d = sa->sadb_address_prefixlen;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2597 sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2598 sel.dport = ((struct sockaddr_in *)(sa + 1))->sin_port;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2599 if (sel.dport)
582ee43dad8e41 Al Viro 2007-07-26 2600 sel.dport_mask = htons(0xffff);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2601
08de61beab8a21 Shinta Sugimoto 2007-02-08 2602 rq = (struct sadb_x_ipsecrequest *)(pol + 1);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2603
08de61beab8a21 Shinta Sugimoto 2007-02-08 2604 /* extract ipsecrequests */
08de61beab8a21 Shinta Sugimoto 2007-02-08 2605 i = 0;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2606 len = pol->sadb_x_policy_len * 8 - sizeof(struct sadb_x_policy);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2607
08de61beab8a21 Shinta Sugimoto 2007-02-08 2608 while (len > 0 && i < XFRM_MAX_DEPTH) {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2609 ret = ipsecrequests_to_migrate(rq, len, &m[i]);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2610 if (ret < 0) {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2611 err = ret;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2612 goto out;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2613 } else {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2614 rq = (struct sadb_x_ipsecrequest *)((u8 *)rq + ret);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2615 len -= ret;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2616 i++;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2617 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2618 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2619
08de61beab8a21 Shinta Sugimoto 2007-02-08 2620 if (!i || len > 0) {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2621 err = -EINVAL;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2622 goto out;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2623 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2624
13c1d18931ebb5 Arnaud Ebalard 2008-10-05 @2625 return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
4ab47d47af20ad Antony Antony 2017-06-06 2626 kma ? &k : NULL, net, NULL);
08de61beab8a21 Shinta Sugimoto 2007-02-08 2627
08de61beab8a21 Shinta Sugimoto 2007-02-08 2628 out:
08de61beab8a21 Shinta Sugimoto 2007-02-08 2629 return err;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2630 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2631 #else
08de61beab8a21 Shinta Sugimoto 2007-02-08 2632 static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
7f6daa635c28ed Stephen Hemminger 2011-03-01 2633 const struct sadb_msg *hdr, void * const *ext_hdrs)
08de61beab8a21 Shinta Sugimoto 2007-02-08 2634 {
08de61beab8a21 Shinta Sugimoto 2007-02-08 2635 return -ENOPROTOOPT;
08de61beab8a21 Shinta Sugimoto 2007-02-08 2636 }
08de61beab8a21 Shinta Sugimoto 2007-02-08 2637 #endif
08de61beab8a21 Shinta Sugimoto 2007-02-08 2638
08de61beab8a21 Shinta Sugimoto 2007-02-08 2639
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes
2021-12-23 0:45 ` [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes Yan Yan
@ 2021-12-26 2:18 ` kernel test robot
0 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2021-12-26 2:18 UTC (permalink / raw)
To: Yan Yan, steffen.klassert
Cc: kbuild-all, herbert, davem, netdev, nharold, benedictwong, maze,
lorenzo, Yan Yan
Hi Yan,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on klassert-ipsec-next/master]
[also build test WARNING on klassert-ipsec/master net-next/master net/master v5.16-rc6 next-20211224]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Yan-Yan/Fix-issues-in-xfrm_migrate/20211223-084725
base: https://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git master
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20211226/202112261010.hDTqK3oK-lkp@intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
# https://github.com/0day-ci/linux/commit/11348c1b6c9b3af9e634611c97eabadb35dffcef
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Yan-Yan/Fix-issues-in-xfrm_migrate/20211223-084725
git checkout 11348c1b6c9b3af9e634611c97eabadb35dffcef
# save the config file to linux build tree
mkdir build_dir
make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/gpio/ kernel/bpf/ net/key/ net/sched/ net/xfrm/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
net/xfrm/xfrm_state.c: In function 'xfrm_state_clone2':
>> net/xfrm/xfrm_state.c:1594:10: warning: returning 'int' from a function with return type 'int *' makes pointer from integer without a cast [-Wint-conversion]
1594 | return err;
| ^~~
net/xfrm/xfrm_state.c: In function 'xfrm_state_migrate':
>> net/xfrm/xfrm_state.c:1675:31: warning: ordered comparison of pointer with integer zero [-Wextra]
1675 | if (xfrm_state_clone2(x, xc) < 0)
| ^
vim +1594 net/xfrm/xfrm_state.c
1588
1589 static int *xfrm_state_clone2(struct xfrm_state *orig,
1590 struct xfrm_state *x)
1591 {
1592 int err = xfrm_init_state(x);
1593 if (err < 0)
> 1594 return err;
1595
1596 x->props.flags = orig->props.flags;
1597 x->props.extra_flags = orig->props.extra_flags;
1598
1599 x->if_id = orig->if_id;
1600 x->tfcpad = orig->tfcpad;
1601 x->replay_maxdiff = orig->replay_maxdiff;
1602 x->replay_maxage = orig->replay_maxage;
1603 memcpy(&x->curlft, &orig->curlft, sizeof(x->curlft));
1604 x->km.state = orig->km.state;
1605 x->km.seq = orig->km.seq;
1606 x->replay = orig->replay;
1607 x->preplay = orig->preplay;
1608
1609 return 0;
1610 }
1611
1612 struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
1613 u32 if_id)
1614 {
1615 unsigned int h;
1616 struct xfrm_state *x = NULL;
1617
1618 spin_lock_bh(&net->xfrm.xfrm_state_lock);
1619
1620 if (m->reqid) {
1621 h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
1622 m->reqid, m->old_family);
1623 hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
1624 if (x->props.mode != m->mode ||
1625 x->id.proto != m->proto)
1626 continue;
1627 if (m->reqid && x->props.reqid != m->reqid)
1628 continue;
1629 if (if_id != 0 && x->if_id != if_id)
1630 continue;
1631 if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
1632 m->old_family) ||
1633 !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
1634 m->old_family))
1635 continue;
1636 xfrm_state_hold(x);
1637 break;
1638 }
1639 } else {
1640 h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
1641 m->old_family);
1642 hlist_for_each_entry(x, net->xfrm.state_bysrc+h, bysrc) {
1643 if (x->props.mode != m->mode ||
1644 x->id.proto != m->proto)
1645 continue;
1646 if (if_id != 0 && x->if_id != if_id)
1647 continue;
1648 if (!xfrm_addr_equal(&x->id.daddr, &m->old_daddr,
1649 m->old_family) ||
1650 !xfrm_addr_equal(&x->props.saddr, &m->old_saddr,
1651 m->old_family))
1652 continue;
1653 xfrm_state_hold(x);
1654 break;
1655 }
1656 }
1657
1658 spin_unlock_bh(&net->xfrm.xfrm_state_lock);
1659
1660 return x;
1661 }
1662 EXPORT_SYMBOL(xfrm_migrate_state_find);
1663
1664 struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
1665 struct xfrm_migrate *m,
1666 struct xfrm_encap_tmpl *encap)
1667 {
1668 struct xfrm_state *xc;
1669
1670 xc = xfrm_state_clone1(x, encap);
1671 if (!xc)
1672 return NULL;
1673
1674 xc->props.family = m->new_family;
> 1675 if (xfrm_state_clone2(x, xc) < 0)
1676 goto error;
1677
1678 memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
1679 memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
1680
1681 /* add state */
1682 if (xfrm_addr_equal(&x->id.daddr, &m->new_daddr, m->new_family)) {
1683 /* a care is needed when the destination address of the
1684 state is to be updated as it is a part of triplet */
1685 xfrm_state_insert(xc);
1686 } else {
1687 if (xfrm_state_add(xc) < 0)
1688 goto error;
1689 }
1690
1691 return xc;
1692 error:
1693 xfrm_state_put(xc);
1694 return NULL;
1695 }
1696 EXPORT_SYMBOL(xfrm_state_migrate);
1697 #endif
1698
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes
2022-01-06 0:52 [PATCH v1 0/2] Fix issues in xfrm_migrate Yan Yan
@ 2022-01-06 0:52 ` Yan Yan
2022-01-12 7:57 ` Steffen Klassert
0 siblings, 1 reply; 8+ messages in thread
From: Yan Yan @ 2022-01-06 0:52 UTC (permalink / raw)
To: Steffen Klassert
Cc: netdev, Herbert Xu, David S . Miller, Jakub Kicinski, lorenzo,
maze, nharold, benedictwong, Yan Yan
xfrm_migrate cannot handle address family change of an xfrm_state.
The symptons are the xfrm_state will be migrated to a wrong address,
and sending as well as receiving packets wil be broken.
This commit fixes it by breaking the original xfrm_state_clone
method into two steps so as to update the props.family before
running xfrm_init_state. As the result, xfrm_state's inner mode,
outer mode, type and IP header length in xfrm_state_migrate can
be updated with the new address family.
Tested with additions to Android's kernel unit test suite:
https://android-review.googlesource.com/c/kernel/tests/+/1885354
Signed-off-by: Yan Yan <evitayan@google.com>
---
net/xfrm/xfrm_state.c | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f52767685b13..cac212039bf9 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1504,8 +1504,8 @@ static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *secu
return 0;
}
-static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
- struct xfrm_encap_tmpl *encap)
+static struct xfrm_state *xfrm_state_clone1(struct xfrm_state *orig,
+ struct xfrm_encap_tmpl *encap)
{
struct net *net = xs_net(orig);
struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1579,8 +1579,20 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
memcpy(&x->mark, &orig->mark, sizeof(x->mark));
memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
- if (xfrm_init_state(x) < 0)
- goto error;
+ return x;
+
+ error:
+ xfrm_state_put(x);
+out:
+ return NULL;
+}
+
+static int xfrm_state_clone2(struct xfrm_state *orig, struct xfrm_state *x)
+{
+ int err = xfrm_init_state(x);
+
+ if (err < 0)
+ return err;
x->props.flags = orig->props.flags;
x->props.extra_flags = orig->props.extra_flags;
@@ -1595,12 +1607,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
x->replay = orig->replay;
x->preplay = orig->preplay;
- return x;
-
- error:
- xfrm_state_put(x);
-out:
- return NULL;
+ return 0;
}
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
@@ -1661,10 +1668,14 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
{
struct xfrm_state *xc;
- xc = xfrm_state_clone(x, encap);
+ xc = xfrm_state_clone1(x, encap);
if (!xc)
return NULL;
+ xc->props.family = m->new_family;
+ if (xfrm_state_clone2(x, xc) < 0)
+ goto error;
+
memcpy(&xc->id.daddr, &m->new_daddr, sizeof(xc->id.daddr));
memcpy(&xc->props.saddr, &m->new_saddr, sizeof(xc->props.saddr));
--
2.34.1.448.ga2b2bfdf31-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes
2022-01-06 0:52 ` [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes Yan Yan
@ 2022-01-12 7:57 ` Steffen Klassert
2022-01-19 0:03 ` Yan Yan
0 siblings, 1 reply; 8+ messages in thread
From: Steffen Klassert @ 2022-01-12 7:57 UTC (permalink / raw)
To: Yan Yan
Cc: netdev, Herbert Xu, David S . Miller, Jakub Kicinski, lorenzo,
maze, nharold, benedictwong
On Wed, Jan 05, 2022 at 04:52:51PM -0800, Yan Yan wrote:
...
> -static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> - struct xfrm_encap_tmpl *encap)
> +static struct xfrm_state *xfrm_state_clone1(struct xfrm_state *orig,
> + struct xfrm_encap_tmpl *encap)
> {
> struct net *net = xs_net(orig);
> struct xfrm_state *x = xfrm_state_alloc(net);
> @@ -1579,8 +1579,20 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> memcpy(&x->mark, &orig->mark, sizeof(x->mark));
> memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
>
> - if (xfrm_init_state(x) < 0)
> - goto error;
> + return x;
> +
> + error:
> + xfrm_state_put(x);
> +out:
> + return NULL;
> +}
> +
> +static int xfrm_state_clone2(struct xfrm_state *orig, struct xfrm_state *x)
I'm not a frind of numbering function names, this just invites to
create xfrm_state_clone3 :)
> +{
> + int err = xfrm_init_state(x);
> +
> + if (err < 0)
> + return err;
>
> x->props.flags = orig->props.flags;
> x->props.extra_flags = orig->props.extra_flags;
> @@ -1595,12 +1607,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> x->replay = orig->replay;
> x->preplay = orig->preplay;
>
> - return x;
> -
> - error:
> - xfrm_state_put(x);
> -out:
> - return NULL;
> + return 0;
> }
>
> struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
> @@ -1661,10 +1668,14 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
> {
> struct xfrm_state *xc;
>
> - xc = xfrm_state_clone(x, encap);
> + xc = xfrm_state_clone1(x, encap);
> if (!xc)
> return NULL;
>
> + xc->props.family = m->new_family;
> + if (xfrm_state_clone2(x, xc) < 0)
> + goto error;
xfrm_state_migrate() is the only function that calls xfrm_state_clone().
Wouldn't it be better to move xfrm_init_state() out of xfrm_state_clone()
and call it afterwards?
This would also fix the replay window initialization on ESN because
currently x->props.flags (which holds XFRM_STATE_ESN) is initialized
after xfrm_init_state().
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes
2022-01-12 7:57 ` Steffen Klassert
@ 2022-01-19 0:03 ` Yan Yan
0 siblings, 0 replies; 8+ messages in thread
From: Yan Yan @ 2022-01-19 0:03 UTC (permalink / raw)
To: Steffen Klassert
Cc: netdev, Herbert Xu, David S . Miller, Jakub Kicinski,
Lorenzo Colitti, Maciej Żenczykowski, nharold, benedictwong
Thanks Steffen, I will pull out xfrm_init_state() as you suggested.
On Tue, Jan 11, 2022 at 11:57 PM Steffen Klassert
<steffen.klassert@secunet.com> wrote:
>
> On Wed, Jan 05, 2022 at 04:52:51PM -0800, Yan Yan wrote:
>
> ...
>
> > -static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> > - struct xfrm_encap_tmpl *encap)
> > +static struct xfrm_state *xfrm_state_clone1(struct xfrm_state *orig,
> > + struct xfrm_encap_tmpl *encap)
> > {
> > struct net *net = xs_net(orig);
> > struct xfrm_state *x = xfrm_state_alloc(net);
> > @@ -1579,8 +1579,20 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> > memcpy(&x->mark, &orig->mark, sizeof(x->mark));
> > memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
> >
> > - if (xfrm_init_state(x) < 0)
> > - goto error;
> > + return x;
> > +
> > + error:
> > + xfrm_state_put(x);
> > +out:
> > + return NULL;
> > +}
> > +
> > +static int xfrm_state_clone2(struct xfrm_state *orig, struct xfrm_state *x)
>
> I'm not a frind of numbering function names, this just invites to
> create xfrm_state_clone3 :)
>
> > +{
> > + int err = xfrm_init_state(x);
> > +
> > + if (err < 0)
> > + return err;
> >
> > x->props.flags = orig->props.flags;
> > x->props.extra_flags = orig->props.extra_flags;
> > @@ -1595,12 +1607,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
> > x->replay = orig->replay;
> > x->preplay = orig->preplay;
> >
> > - return x;
> > -
> > - error:
> > - xfrm_state_put(x);
> > -out:
> > - return NULL;
> > + return 0;
> > }
> >
> > struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
> > @@ -1661,10 +1668,14 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
> > {
> > struct xfrm_state *xc;
> >
> > - xc = xfrm_state_clone(x, encap);
> > + xc = xfrm_state_clone1(x, encap);
> > if (!xc)
> > return NULL;
> >
> > + xc->props.family = m->new_family;
> > + if (xfrm_state_clone2(x, xc) < 0)
> > + goto error;
>
> xfrm_state_migrate() is the only function that calls xfrm_state_clone().
> Wouldn't it be better to move xfrm_init_state() out of xfrm_state_clone()
> and call it afterwards?
>
> This would also fix the replay window initialization on ESN because
> currently x->props.flags (which holds XFRM_STATE_ESN) is initialized
> after xfrm_init_state().
>
--
--
Best,
Yan
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-01-19 0:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-12-23 0:45 [PATCH v1 0/2] Fix issues in xfrm_migrate Yan Yan
2021-12-23 0:45 ` [PATCH v1 1/2] xfrm: Check if_id " Yan Yan
2021-12-25 18:30 ` kernel test robot
2021-12-23 0:45 ` [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes Yan Yan
2021-12-26 2:18 ` kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2022-01-06 0:52 [PATCH v1 0/2] Fix issues in xfrm_migrate Yan Yan
2022-01-06 0:52 ` [PATCH v1 2/2] xfrm: Fix xfrm migrate issues when address family changes Yan Yan
2022-01-12 7:57 ` Steffen Klassert
2022-01-19 0:03 ` Yan Yan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).