All of lore.kernel.org
 help / color / mirror / Atom feed
* pull request (net): ipsec 2017-12-22
@ 2017-12-22  9:44 Steffen Klassert
  2017-12-22  9:44 ` [PATCH 1/8] xfrm: check id proto in validate_tmpl() Steffen Klassert
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

1) Check for valid id proto in validate_tmpl(), otherwise
   we may trigger a warning in xfrm_state_fini().
   From Cong Wang.

2) Fix a typo on XFRMA_OUTPUT_MARK policy attribute.
   From Michal Kubecek.

3) Verify the state is valid when encap_type < 0,
   otherwise we may crash on IPsec GRO .
   From Aviv Heller.

4) Fix stack-out-of-bounds read on socket policy lookup.
   We access the flowi of the wrong address family in the
   IPv4 mapped IPv6 case, fix this by catching address
   family missmatches before we do the lookup.

5) fix xfrm_do_migrate() with AEAD to copy the geniv
   field too. Otherwise the state is not fully initialized
   and migration fails. From Antony Antony.

6) Fix stack-out-of-bounds with misconfigured transport
   mode policies. Our policy template validation is not
   strict enough. It is possible to configure policies
   with transport mode template where the address family
   of the template does not match the selectors address
   family. Fix this by refusing such a configuration,
   address family can not change on transport mode.

7) Fix a policy reference leak when reusing pcpu xdst
   entry. From Florian Westphal.

8) Reinject transport-mode packets through tasklet,
   otherwise it is possible to reate a recursion
   loop. From Herbert Xu.

Please pull or let me know if there are problems.

Thanks!

The following changes since commit d51aae68b142f48232257e96ce317db25445418d:

  net: sched: cbq: create block for q->link.block (2017-11-28 16:04:26 -0500)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git master

for you to fetch changes up to acf568ee859f098279eadf551612f103afdacb4e:

  xfrm: Reinject transport-mode packets through tasklet (2017-12-19 08:23:21 +0100)

----------------------------------------------------------------
Antony Antony (1):
      xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM)

Aviv Heller (1):
      xfrm: Fix xfrm_input() to verify state is valid when (encap_type < 0)

Cong Wang (1):
      xfrm: check id proto in validate_tmpl()

Florian Westphal (1):
      xfrm: put policies when reusing pcpu xdst entry

Herbert Xu (1):
      xfrm: Reinject transport-mode packets through tasklet

Michal Kubecek (1):
      xfrm: fix XFRMA_OUTPUT_MARK policy entry

Steffen Klassert (2):
      xfrm: Fix stack-out-of-bounds read on socket policy lookup.
      xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies.

 include/net/xfrm.h     |  3 +++
 net/ipv4/xfrm4_input.c | 12 ++++++++-
 net/ipv6/xfrm6_input.c | 10 +++++++-
 net/xfrm/xfrm_input.c  | 69 +++++++++++++++++++++++++++++++++++++++++++++++++-
 net/xfrm/xfrm_policy.c |  9 ++++++-
 net/xfrm/xfrm_state.c  |  1 +
 net/xfrm/xfrm_user.c   | 26 ++++++++++++++++++-
 7 files changed, 125 insertions(+), 5 deletions(-)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/8] xfrm: check id proto in validate_tmpl()
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
@ 2017-12-22  9:44 ` Steffen Klassert
  2017-12-22  9:44 ` [PATCH 2/8] xfrm: fix XFRMA_OUTPUT_MARK policy entry Steffen Klassert
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Cong Wang <xiyou.wangcong@gmail.com>

syzbot reported a kernel warning in xfrm_state_fini(), which
indicates that we have entries left in the list
net->xfrm.state_all whose proto is zero. And
xfrm_id_proto_match() doesn't consider them as a match with
IPSEC_PROTO_ANY in this case.

Proto with value 0 is probably not a valid value, at least
verify_newsa_info() doesn't consider it valid either.

This patch fixes it by checking the proto value in
validate_tmpl() and rejecting invalid ones, like what iproute2
does in xfrm_xfrmproto_getbyname().

Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_user.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 983b0233767b..c2cfcc6fdb34 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1445,6 +1445,21 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
 		default:
 			return -EINVAL;
 		}
+
+		switch (ut[i].id.proto) {
+		case IPPROTO_AH:
+		case IPPROTO_ESP:
+		case IPPROTO_COMP:
+#if IS_ENABLED(CONFIG_IPV6)
+		case IPPROTO_ROUTING:
+		case IPPROTO_DSTOPTS:
+#endif
+		case IPSEC_PROTO_ANY:
+			break;
+		default:
+			return -EINVAL;
+		}
+
 	}
 
 	return 0;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/8] xfrm: fix XFRMA_OUTPUT_MARK policy entry
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
  2017-12-22  9:44 ` [PATCH 1/8] xfrm: check id proto in validate_tmpl() Steffen Klassert
@ 2017-12-22  9:44 ` Steffen Klassert
  2017-12-22  9:44 ` [PATCH 3/8] xfrm: Fix xfrm_input() to verify state is valid when (encap_type < 0) Steffen Klassert
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Michal Kubecek <mkubecek@suse.cz>

This seems to be an obvious typo, NLA_U32 is type of the attribute, not its
(minimal) length.

Fixes: 077fbac405bf ("net: xfrm: support setting an output mark.")
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c2cfcc6fdb34..ff58c37469d6 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2485,7 +2485,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
 	[XFRMA_PROTO]		= { .type = NLA_U8 },
 	[XFRMA_ADDRESS_FILTER]	= { .len = sizeof(struct xfrm_address_filter) },
 	[XFRMA_OFFLOAD_DEV]	= { .len = sizeof(struct xfrm_user_offload) },
-	[XFRMA_OUTPUT_MARK]	= { .len = NLA_U32 },
+	[XFRMA_OUTPUT_MARK]	= { .type = NLA_U32 },
 };
 
 static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/8] xfrm: Fix xfrm_input() to verify state is valid when (encap_type < 0)
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
  2017-12-22  9:44 ` [PATCH 1/8] xfrm: check id proto in validate_tmpl() Steffen Klassert
  2017-12-22  9:44 ` [PATCH 2/8] xfrm: fix XFRMA_OUTPUT_MARK policy entry Steffen Klassert
@ 2017-12-22  9:44 ` Steffen Klassert
  2017-12-22  9:44 ` [PATCH 4/8] xfrm: Fix stack-out-of-bounds read on socket policy lookup Steffen Klassert
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Aviv Heller <avivh@mellanox.com>

Code path when (encap_type < 0) does not verify the state is valid
before progressing.

This will result in a crash if, for instance, x->km.state ==
XFRM_STATE_ACQ.

Fixes: 7785bba299a8 ("esp: Add a software GRO codepath")
Signed-off-by: Aviv Heller <avivh@mellanox.com>
Signed-off-by: Yevgeny Kliteynik <kliteyn@mellanox.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_input.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 347ab31574d5..da6447389ffb 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -207,7 +207,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 	xfrm_address_t *daddr;
 	struct xfrm_mode *inner_mode;
 	u32 mark = skb->mark;
-	unsigned int family;
+	unsigned int family = AF_UNSPEC;
 	int decaps = 0;
 	int async = 0;
 	bool xfrm_gro = false;
@@ -216,6 +216,16 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 
 	if (encap_type < 0) {
 		x = xfrm_input_state(skb);
+
+		if (unlikely(x->km.state != XFRM_STATE_VALID)) {
+			if (x->km.state == XFRM_STATE_ACQ)
+				XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR);
+			else
+				XFRM_INC_STATS(net,
+					       LINUX_MIB_XFRMINSTATEINVALID);
+			goto drop;
+		}
+
 		family = x->outer_mode->afinfo->family;
 
 		/* An encap_type of -1 indicates async resumption. */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/8] xfrm: Fix stack-out-of-bounds read on socket policy lookup.
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
                   ` (2 preceding siblings ...)
  2017-12-22  9:44 ` [PATCH 3/8] xfrm: Fix xfrm_input() to verify state is valid when (encap_type < 0) Steffen Klassert
@ 2017-12-22  9:44 ` Steffen Klassert
  2017-12-22  9:44 ` [PATCH 5/8] xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM) Steffen Klassert
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

When we do tunnel or beet mode, we pass saddr and daddr from the
template to xfrm_state_find(), this is ok. On transport mode,
we pass the addresses from the flowi, assuming that the IP
addresses (and address family) don't change during transformation.
This assumption is wrong in the IPv4 mapped IPv6 case, packet
is IPv4 and template is IPv6.

Fix this by catching address family missmatches of the policy
and the flow already before we do the lookup.

Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_policy.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 9542975eb2f9..038ec68f6901 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1168,9 +1168,15 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
  again:
 	pol = rcu_dereference(sk->sk_policy[dir]);
 	if (pol != NULL) {
-		bool match = xfrm_selector_match(&pol->selector, fl, family);
+		bool match;
 		int err = 0;
 
+		if (pol->family != family) {
+			pol = NULL;
+			goto out;
+		}
+
+		match = xfrm_selector_match(&pol->selector, fl, family);
 		if (match) {
 			if ((sk->sk_mark & pol->mark.m) != pol->mark.v) {
 				pol = NULL;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/8] xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM)
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
                   ` (3 preceding siblings ...)
  2017-12-22  9:44 ` [PATCH 4/8] xfrm: Fix stack-out-of-bounds read on socket policy lookup Steffen Klassert
@ 2017-12-22  9:44 ` Steffen Klassert
  2017-12-22  9:44 ` [PATCH 6/8] xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies Steffen Klassert
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Antony Antony <antony@phenome.org>

copy geniv when cloning the xfrm state.

x->geniv was not copied to the new state and migration would fail.

xfrm_do_migrate
  ..
  xfrm_state_clone()
   ..
   ..
   esp_init_aead()
   crypto_alloc_aead()
    crypto_alloc_tfm()
     crypto_find_alg() return EAGAIN and failed

Signed-off-by: Antony Antony <antony@phenome.org>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_state.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1f5cee2269af..88d0a563e141 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1344,6 +1344,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
 
 	if (orig->aead) {
 		x->aead = xfrm_algo_aead_clone(orig->aead);
+		x->geniv = orig->geniv;
 		if (!x->aead)
 			goto error;
 	}
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/8] xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies.
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
                   ` (4 preceding siblings ...)
  2017-12-22  9:44 ` [PATCH 5/8] xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM) Steffen Klassert
@ 2017-12-22  9:44 ` Steffen Klassert
  2017-12-22  9:45 ` [PATCH 7/8] xfrm: put policies when reusing pcpu xdst entry Steffen Klassert
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:44 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

On policies with a transport mode template, we pass the addresses
from the flowi to xfrm_state_find(), assuming that the IP addresses
(and address family) don't change during transformation.

Unfortunately our policy template validation is not strict enough.
It is possible to configure policies with transport mode template
where the address family of the template does not match the selectors
address family. This lead to stack-out-of-bound reads because
we compare arddesses of the wrong family. Fix this by refusing
such a configuration, address family can not change on transport
mode.

We use the assumption that, on transport mode, the first templates
address family must match the address family of the policy selector.
Subsequent transport mode templates must mach the address family of
the previous template.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_user.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ff58c37469d6..bdb48e5dba04 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1419,11 +1419,14 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
 
 static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
 {
+	u16 prev_family;
 	int i;
 
 	if (nr > XFRM_MAX_DEPTH)
 		return -EINVAL;
 
+	prev_family = family;
+
 	for (i = 0; i < nr; i++) {
 		/* We never validated the ut->family value, so many
 		 * applications simply leave it at zero.  The check was
@@ -1435,6 +1438,12 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
 		if (!ut[i].family)
 			ut[i].family = family;
 
+		if ((ut[i].mode == XFRM_MODE_TRANSPORT) &&
+		    (ut[i].family != prev_family))
+			return -EINVAL;
+
+		prev_family = ut[i].family;
+
 		switch (ut[i].family) {
 		case AF_INET:
 			break;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/8] xfrm: put policies when reusing pcpu xdst entry
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
                   ` (5 preceding siblings ...)
  2017-12-22  9:44 ` [PATCH 6/8] xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies Steffen Klassert
@ 2017-12-22  9:45 ` Steffen Klassert
  2017-12-22  9:45 ` [PATCH 8/8] xfrm: Reinject transport-mode packets through tasklet Steffen Klassert
  2017-12-27 16:00 ` pull request (net): ipsec 2017-12-22 David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:45 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Florian Westphal <fw@strlen.de>

We need to put the policies when re-using the pcpu xdst entry, else
this leaks the reference.

Fixes: ec30d78c14a813db39a647b6a348b428 ("xfrm: add xdst pcpu cache")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_policy.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 038ec68f6901..70aa5cb0c659 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1839,6 +1839,7 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
 		   sizeof(struct xfrm_policy *) * num_pols) == 0 &&
 	    xfrm_xdst_can_reuse(xdst, xfrm, err)) {
 		dst_hold(&xdst->u.dst);
+		xfrm_pols_put(pols, num_pols);
 		while (err > 0)
 			xfrm_state_put(xfrm[--err]);
 		return xdst;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 8/8] xfrm: Reinject transport-mode packets through tasklet
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
                   ` (6 preceding siblings ...)
  2017-12-22  9:45 ` [PATCH 7/8] xfrm: put policies when reusing pcpu xdst entry Steffen Klassert
@ 2017-12-22  9:45 ` Steffen Klassert
  2017-12-27 16:00 ` pull request (net): ipsec 2017-12-22 David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2017-12-22  9:45 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Herbert Xu <herbert@gondor.apana.org.au>

This is an old bugbear of mine:

https://www.mail-archive.com/netdev@vger.kernel.org/msg03894.html

By crafting special packets, it is possible to cause recursion
in our kernel when processing transport-mode packets at levels
that are only limited by packet size.

The easiest one is with DNAT, but an even worse one is where
UDP encapsulation is used in which case you just have to insert
an UDP encapsulation header in between each level of recursion.

This patch avoids this problem by reinjecting tranport-mode packets
through a tasklet.

Fixes: b05e106698d9 ("[IPV4/6]: Netfilter IPsec input hooks")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 include/net/xfrm.h     |  3 +++
 net/ipv4/xfrm4_input.c | 12 ++++++++++-
 net/ipv6/xfrm6_input.c | 10 ++++++++-
 net/xfrm/xfrm_input.c  | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index dc28a98ce97c..ae35991b5877 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1570,6 +1570,9 @@ int xfrm_init_state(struct xfrm_state *x);
 int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
 int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
 int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
+int xfrm_trans_queue(struct sk_buff *skb,
+		     int (*finish)(struct net *, struct sock *,
+				   struct sk_buff *));
 int xfrm_output_resume(struct sk_buff *skb, int err);
 int xfrm_output(struct sock *sk, struct sk_buff *skb);
 int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index e50b7fea57ee..bcfc00e88756 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -23,6 +23,12 @@ int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb)
 	return xfrm4_extract_header(skb);
 }
 
+static int xfrm4_rcv_encap_finish2(struct net *net, struct sock *sk,
+				   struct sk_buff *skb)
+{
+	return dst_input(skb);
+}
+
 static inline int xfrm4_rcv_encap_finish(struct net *net, struct sock *sk,
 					 struct sk_buff *skb)
 {
@@ -33,7 +39,11 @@ static inline int xfrm4_rcv_encap_finish(struct net *net, struct sock *sk,
 					 iph->tos, skb->dev))
 			goto drop;
 	}
-	return dst_input(skb);
+
+	if (xfrm_trans_queue(skb, xfrm4_rcv_encap_finish2))
+		goto drop;
+
+	return 0;
 drop:
 	kfree_skb(skb);
 	return NET_RX_DROP;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index fe04e23af986..841f4a07438e 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -32,6 +32,14 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi,
 }
 EXPORT_SYMBOL(xfrm6_rcv_spi);
 
+static int xfrm6_transport_finish2(struct net *net, struct sock *sk,
+				   struct sk_buff *skb)
+{
+	if (xfrm_trans_queue(skb, ip6_rcv_finish))
+		__kfree_skb(skb);
+	return -1;
+}
+
 int xfrm6_transport_finish(struct sk_buff *skb, int async)
 {
 	struct xfrm_offload *xo = xfrm_offload(skb);
@@ -56,7 +64,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
 
 	NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
 		dev_net(skb->dev), NULL, skb, skb->dev, NULL,
-		ip6_rcv_finish);
+		xfrm6_transport_finish2);
 	return -1;
 }
 
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index da6447389ffb..3f6f6f8c9fa5 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -8,15 +8,29 @@
  *
  */
 
+#include <linux/bottom_half.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/percpu.h>
 #include <net/dst.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/ip_tunnels.h>
 #include <net/ip6_tunnel.h>
 
+struct xfrm_trans_tasklet {
+	struct tasklet_struct tasklet;
+	struct sk_buff_head queue;
+};
+
+struct xfrm_trans_cb {
+	int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb);
+};
+
+#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0]))
+
 static struct kmem_cache *secpath_cachep __read_mostly;
 
 static DEFINE_SPINLOCK(xfrm_input_afinfo_lock);
@@ -25,6 +39,8 @@ static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[AF_INET6 + 1];
 static struct gro_cells gro_cells;
 static struct net_device xfrm_napi_dev;
 
+static DEFINE_PER_CPU(struct xfrm_trans_tasklet, xfrm_trans_tasklet);
+
 int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo)
 {
 	int err = 0;
@@ -477,9 +493,41 @@ int xfrm_input_resume(struct sk_buff *skb, int nexthdr)
 }
 EXPORT_SYMBOL(xfrm_input_resume);
 
+static void xfrm_trans_reinject(unsigned long data)
+{
+	struct xfrm_trans_tasklet *trans = (void *)data;
+	struct sk_buff_head queue;
+	struct sk_buff *skb;
+
+	__skb_queue_head_init(&queue);
+	skb_queue_splice_init(&trans->queue, &queue);
+
+	while ((skb = __skb_dequeue(&queue)))
+		XFRM_TRANS_SKB_CB(skb)->finish(dev_net(skb->dev), NULL, skb);
+}
+
+int xfrm_trans_queue(struct sk_buff *skb,
+		     int (*finish)(struct net *, struct sock *,
+				   struct sk_buff *))
+{
+	struct xfrm_trans_tasklet *trans;
+
+	trans = this_cpu_ptr(&xfrm_trans_tasklet);
+
+	if (skb_queue_len(&trans->queue) >= netdev_max_backlog)
+		return -ENOBUFS;
+
+	XFRM_TRANS_SKB_CB(skb)->finish = finish;
+	skb_queue_tail(&trans->queue, skb);
+	tasklet_schedule(&trans->tasklet);
+	return 0;
+}
+EXPORT_SYMBOL(xfrm_trans_queue);
+
 void __init xfrm_input_init(void)
 {
 	int err;
+	int i;
 
 	init_dummy_netdev(&xfrm_napi_dev);
 	err = gro_cells_init(&gro_cells, &xfrm_napi_dev);
@@ -490,4 +538,13 @@ void __init xfrm_input_init(void)
 					   sizeof(struct sec_path),
 					   0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
 					   NULL);
+
+	for_each_possible_cpu(i) {
+		struct xfrm_trans_tasklet *trans;
+
+		trans = &per_cpu(xfrm_trans_tasklet, i);
+		__skb_queue_head_init(&trans->queue);
+		tasklet_init(&trans->tasklet, xfrm_trans_reinject,
+			     (unsigned long)trans);
+	}
 }
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: pull request (net): ipsec 2017-12-22
  2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
                   ` (7 preceding siblings ...)
  2017-12-22  9:45 ` [PATCH 8/8] xfrm: Reinject transport-mode packets through tasklet Steffen Klassert
@ 2017-12-27 16:00 ` David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2017-12-27 16:00 UTC (permalink / raw)
  To: steffen.klassert; +Cc: herbert, netdev

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 22 Dec 2017 10:44:53 +0100

> 1) Check for valid id proto in validate_tmpl(), otherwise
>    we may trigger a warning in xfrm_state_fini().
>    From Cong Wang.
> 
> 2) Fix a typo on XFRMA_OUTPUT_MARK policy attribute.
>    From Michal Kubecek.
> 
> 3) Verify the state is valid when encap_type < 0,
>    otherwise we may crash on IPsec GRO .
>    From Aviv Heller.
> 
> 4) Fix stack-out-of-bounds read on socket policy lookup.
>    We access the flowi of the wrong address family in the
>    IPv4 mapped IPv6 case, fix this by catching address
>    family missmatches before we do the lookup.
> 
> 5) fix xfrm_do_migrate() with AEAD to copy the geniv
>    field too. Otherwise the state is not fully initialized
>    and migration fails. From Antony Antony.
> 
> 6) Fix stack-out-of-bounds with misconfigured transport
>    mode policies. Our policy template validation is not
>    strict enough. It is possible to configure policies
>    with transport mode template where the address family
>    of the template does not match the selectors address
>    family. Fix this by refusing such a configuration,
>    address family can not change on transport mode.
> 
> 7) Fix a policy reference leak when reusing pcpu xdst
>    entry. From Florian Westphal.
> 
> 8) Reinject transport-mode packets through tasklet,
>    otherwise it is possible to reate a recursion
>    loop. From Herbert Xu.
> 
> Please pull or let me know if there are problems.

Pulled, thank you very much!

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-12-27 16:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-22  9:44 pull request (net): ipsec 2017-12-22 Steffen Klassert
2017-12-22  9:44 ` [PATCH 1/8] xfrm: check id proto in validate_tmpl() Steffen Klassert
2017-12-22  9:44 ` [PATCH 2/8] xfrm: fix XFRMA_OUTPUT_MARK policy entry Steffen Klassert
2017-12-22  9:44 ` [PATCH 3/8] xfrm: Fix xfrm_input() to verify state is valid when (encap_type < 0) Steffen Klassert
2017-12-22  9:44 ` [PATCH 4/8] xfrm: Fix stack-out-of-bounds read on socket policy lookup Steffen Klassert
2017-12-22  9:44 ` [PATCH 5/8] xfrm: fix xfrm_do_migrate() with AEAD e.g(AES-GCM) Steffen Klassert
2017-12-22  9:44 ` [PATCH 6/8] xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies Steffen Klassert
2017-12-22  9:45 ` [PATCH 7/8] xfrm: put policies when reusing pcpu xdst entry Steffen Klassert
2017-12-22  9:45 ` [PATCH 8/8] xfrm: Reinject transport-mode packets through tasklet Steffen Klassert
2017-12-27 16:00 ` pull request (net): ipsec 2017-12-22 David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.