All of lore.kernel.org
 help / color / mirror / Atom feed
* pull request (net): ipsec 2020-03-27
@ 2020-03-27  8:09 Steffen Klassert
  2020-03-27  8:10 ` [PATCH 1/8] xfrm: handle NETDEV_UNREGISTER for xfrm device Steffen Klassert
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:09 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

1) Handle NETDEV_UNREGISTER for xfrm device to handle asynchronous
   unregister events cleanly. From Raed Salem.

2) Fix vti6 tunnel inter address family TX through bpf_redirect().
   From Nicolas Dichtel.

3) Fix lenght check in verify_sec_ctx_len() to avoid a
   slab-out-of-bounds. From Xin Long.

4) Add a missing verify_sec_ctx_len check in xfrm_add_acquire
   to avoid a possible out-of-bounds to access. From Xin Long.

5) Use built-in RCU list checking of hlist_for_each_entry_rcu
   to silence false lockdep warning in __xfrm6_tunnel_spi_lookup
   when CONFIG_PROVE_RCU_LIST is enabled. From Madhuparna Bhowmik.

6) Fix a panic on esp offload when crypto is done asynchronously.
   From Xin Long.

7) Fix a skb memory leak in an error path of vti6_rcv.
   From Torsten Hilbrich.

8) Fix a race that can lead to a doulbe free in xfrm_policy_timer.
   From Xin Long.

Please pull or let me know if there are problems.

Thanks!

The following changes since commit a444ad1432c5a0fb3bd43fc9ac39fb88b1fb141e:

  Merge branch 'netdevsim-fix-several-bugs-in-netdevsim-module' (2020-02-03 15:38:50 -0800)

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 4c59406ed00379c8663f8663d82b2537467ce9d7:

  xfrm: policy: Fix doulbe free in xfrm_policy_timer (2020-03-24 06:56:54 +0100)

----------------------------------------------------------------
Madhuparna Bhowmik (1):
      ipv6: xfrm6_tunnel.c: Use built-in RCU list checking

Nicolas Dichtel (1):
      vti[6]: fix packet tx through bpf_redirect() in XinY cases

Raed Salem (1):
      xfrm: handle NETDEV_UNREGISTER for xfrm device

Torsten Hilbrich (1):
      vti6: Fix memory leak of skb if input policy check fails

Xin Long (3):
      xfrm: fix uctx len check in verify_sec_ctx_len
      xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire
      esp: remove the skb from the chain when it's enqueued in cryptd_wq

YueHaibing (1):
      xfrm: policy: Fix doulbe free in xfrm_policy_timer

 net/ipv4/Kconfig        |  1 +
 net/ipv4/ip_vti.c       | 38 ++++++++++++++++++++++++++++++--------
 net/ipv6/ip6_vti.c      | 34 ++++++++++++++++++++++++++--------
 net/ipv6/xfrm6_tunnel.c |  2 +-
 net/xfrm/xfrm_device.c  |  9 +++++----
 net/xfrm/xfrm_policy.c  |  2 ++
 net/xfrm/xfrm_user.c    |  6 +++++-
 7 files changed, 70 insertions(+), 22 deletions(-)

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

* [PATCH 1/8] xfrm: handle NETDEV_UNREGISTER for xfrm device
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 2/8] vti[6]: fix packet tx through bpf_redirect() in XinY cases Steffen Klassert
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Raed Salem <raeds@mellanox.com>

This patch to handle the asynchronous unregister
device event so the device IPsec offload resources
could be cleanly released.

Fixes: e4db5b61c572 ("xfrm: policy: remove pcpu policy cache")
Signed-off-by: Raed Salem <raeds@mellanox.com>
Reviewed-by: Boris Pismenny <borisp@mellanox.com>
Reviewed-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_device.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 50f567a88f45..3231ec628544 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -383,6 +383,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
 		return xfrm_dev_feat_change(dev);
 
 	case NETDEV_DOWN:
+	case NETDEV_UNREGISTER:
 		return xfrm_dev_down(dev);
 	}
 	return NOTIFY_DONE;
-- 
2.17.1


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

* [PATCH 2/8] vti[6]: fix packet tx through bpf_redirect() in XinY cases
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
  2020-03-27  8:10 ` [PATCH 1/8] xfrm: handle NETDEV_UNREGISTER for xfrm device Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 3/8] xfrm: fix uctx len check in verify_sec_ctx_len Steffen Klassert
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Nicolas Dichtel <nicolas.dichtel@6wind.com>

I forgot the 4in6/6in4 cases in my previous patch. Let's fix them.

Fixes: 95224166a903 ("vti[6]: fix packet tx through bpf_redirect()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv4/Kconfig   |  1 +
 net/ipv4/ip_vti.c  | 38 ++++++++++++++++++++++++++++++--------
 net/ipv6/ip6_vti.c | 32 +++++++++++++++++++++++++-------
 3 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index f96bd489b362..6490b845e17b 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -303,6 +303,7 @@ config SYN_COOKIES
 
 config NET_IPVTI
 	tristate "Virtual (secure) IP: tunneling"
+	depends on IPV6 || IPV6=n
 	select INET_TUNNEL
 	select NET_IP_TUNNEL
 	select XFRM
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 37cddd18f282..1b4e6f298648 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -187,17 +187,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
 	int mtu;
 
 	if (!dst) {
-		struct rtable *rt;
-
-		fl->u.ip4.flowi4_oif = dev->ifindex;
-		fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
-		rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
-		if (IS_ERR(rt)) {
+		switch (skb->protocol) {
+		case htons(ETH_P_IP): {
+			struct rtable *rt;
+
+			fl->u.ip4.flowi4_oif = dev->ifindex;
+			fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+			rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
+			if (IS_ERR(rt)) {
+				dev->stats.tx_carrier_errors++;
+				goto tx_error_icmp;
+			}
+			dst = &rt->dst;
+			skb_dst_set(skb, dst);
+			break;
+		}
+#if IS_ENABLED(CONFIG_IPV6)
+		case htons(ETH_P_IPV6):
+			fl->u.ip6.flowi6_oif = dev->ifindex;
+			fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+			dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
+			if (dst->error) {
+				dst_release(dst);
+				dst = NULL;
+				dev->stats.tx_carrier_errors++;
+				goto tx_error_icmp;
+			}
+			skb_dst_set(skb, dst);
+			break;
+#endif
+		default:
 			dev->stats.tx_carrier_errors++;
 			goto tx_error_icmp;
 		}
-		dst = &rt->dst;
-		skb_dst_set(skb, dst);
 	}
 
 	dst_hold(dst);
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 524006aa0d78..56e642efefff 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -450,15 +450,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
 	int mtu;
 
 	if (!dst) {
-		fl->u.ip6.flowi6_oif = dev->ifindex;
-		fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
-		dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
-		if (dst->error) {
-			dst_release(dst);
-			dst = NULL;
+		switch (skb->protocol) {
+		case htons(ETH_P_IP): {
+			struct rtable *rt;
+
+			fl->u.ip4.flowi4_oif = dev->ifindex;
+			fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+			rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
+			if (IS_ERR(rt))
+				goto tx_err_link_failure;
+			dst = &rt->dst;
+			skb_dst_set(skb, dst);
+			break;
+		}
+		case htons(ETH_P_IPV6):
+			fl->u.ip6.flowi6_oif = dev->ifindex;
+			fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+			dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
+			if (dst->error) {
+				dst_release(dst);
+				dst = NULL;
+				goto tx_err_link_failure;
+			}
+			skb_dst_set(skb, dst);
+			break;
+		default:
 			goto tx_err_link_failure;
 		}
-		skb_dst_set(skb, dst);
 	}
 
 	dst_hold(dst);
-- 
2.17.1


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

* [PATCH 3/8] xfrm: fix uctx len check in verify_sec_ctx_len
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
  2020-03-27  8:10 ` [PATCH 1/8] xfrm: handle NETDEV_UNREGISTER for xfrm device Steffen Klassert
  2020-03-27  8:10 ` [PATCH 2/8] vti[6]: fix packet tx through bpf_redirect() in XinY cases Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 4/8] xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire Steffen Klassert
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Xin Long <lucien.xin@gmail.com>

It's not sufficient to do 'uctx->len != (sizeof(struct xfrm_user_sec_ctx) +
uctx->ctx_len)' check only, as uctx->len may be greater than nla_len(rt),
in which case it will cause slab-out-of-bounds when accessing uctx->ctx_str
later.

This patch is to fix it by return -EINVAL when uctx->len > nla_len(rt).

Fixes: df71837d5024 ("[LSM-IPSec]: Security association restriction.")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_user.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b88ba45ff1ac..38ff02d31402 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -110,7 +110,8 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
 		return 0;
 
 	uctx = nla_data(rt);
-	if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
+	if (uctx->len > nla_len(rt) ||
+	    uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len))
 		return -EINVAL;
 
 	return 0;
-- 
2.17.1


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

* [PATCH 4/8] xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
                   ` (2 preceding siblings ...)
  2020-03-27  8:10 ` [PATCH 3/8] xfrm: fix uctx len check in verify_sec_ctx_len Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 5/8] ipv6: xfrm6_tunnel.c: Use built-in RCU list checking Steffen Klassert
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Xin Long <lucien.xin@gmail.com>

Without doing verify_sec_ctx_len() check in xfrm_add_acquire(), it may be
out-of-bounds to access uctx->ctx_str with uctx->ctx_len, as noticed by
syz:

  BUG: KASAN: slab-out-of-bounds in selinux_xfrm_alloc_user+0x237/0x430
  Read of size 768 at addr ffff8880123be9b4 by task syz-executor.1/11650

  Call Trace:
   dump_stack+0xe8/0x16e
   print_address_description.cold.3+0x9/0x23b
   kasan_report.cold.4+0x64/0x95
   memcpy+0x1f/0x50
   selinux_xfrm_alloc_user+0x237/0x430
   security_xfrm_policy_alloc+0x5c/0xb0
   xfrm_policy_construct+0x2b1/0x650
   xfrm_add_acquire+0x21d/0xa10
   xfrm_user_rcv_msg+0x431/0x6f0
   netlink_rcv_skb+0x15a/0x410
   xfrm_netlink_rcv+0x6d/0x90
   netlink_unicast+0x50e/0x6a0
   netlink_sendmsg+0x8ae/0xd40
   sock_sendmsg+0x133/0x170
   ___sys_sendmsg+0x834/0x9a0
   __sys_sendmsg+0x100/0x1e0
   do_syscall_64+0xe5/0x660
   entry_SYSCALL_64_after_hwframe+0x6a/0xdf

So fix it by adding the missing verify_sec_ctx_len check there.

Fixes: 980ebd25794f ("[IPSEC]: Sync series - acquire insert")
Reported-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_user.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 38ff02d31402..e6cfaa680ef3 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2274,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	xfrm_mark_get(attrs, &mark);
 
 	err = verify_newpolicy_info(&ua->policy);
+	if (err)
+		goto free_state;
+	err = verify_sec_ctx_len(attrs);
 	if (err)
 		goto free_state;
 
-- 
2.17.1


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

* [PATCH 5/8] ipv6: xfrm6_tunnel.c: Use built-in RCU list checking
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
                   ` (3 preceding siblings ...)
  2020-03-27  8:10 ` [PATCH 4/8] xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 6/8] esp: remove the skb from the chain when it's enqueued in cryptd_wq Steffen Klassert
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>

hlist_for_each_entry_rcu() has built-in RCU and lock checking.

Pass cond argument to list_for_each_entry_rcu() to silence
false lockdep warning when CONFIG_PROVE_RCU_LIST is enabled
by default.

Signed-off-by: Madhuparna Bhowmik <madhuparnabhowmik10@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/xfrm6_tunnel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index e11bdb0aaa15..25b7ebda2fab 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -78,7 +78,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const
 
 	hlist_for_each_entry_rcu(x6spi,
 			     &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
-			     list_byaddr) {
+			     list_byaddr, lockdep_is_held(&xfrm6_tunnel_spi_lock)) {
 		if (xfrm6_addr_equal(&x6spi->addr, saddr))
 			return x6spi;
 	}
-- 
2.17.1


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

* [PATCH 6/8] esp: remove the skb from the chain when it's enqueued in cryptd_wq
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
                   ` (4 preceding siblings ...)
  2020-03-27  8:10 ` [PATCH 5/8] ipv6: xfrm6_tunnel.c: Use built-in RCU list checking Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 7/8] vti6: Fix memory leak of skb if input policy check fails Steffen Klassert
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Xin Long <lucien.xin@gmail.com>

Xiumei found a panic in esp offload:

  BUG: unable to handle kernel NULL pointer dereference at 0000000000000020
  RIP: 0010:esp_output_done+0x101/0x160 [esp4]
  Call Trace:
   ? esp_output+0x180/0x180 [esp4]
   cryptd_aead_crypt+0x4c/0x90
   cryptd_queue_worker+0x6e/0xa0
   process_one_work+0x1a7/0x3b0
   worker_thread+0x30/0x390
   ? create_worker+0x1a0/0x1a0
   kthread+0x112/0x130
   ? kthread_flush_work_fn+0x10/0x10
   ret_from_fork+0x35/0x40

It was caused by that skb secpath is used in esp_output_done() after it's
been released elsewhere.

The tx path for esp offload is:

  __dev_queue_xmit()->
    validate_xmit_skb_list()->
      validate_xmit_xfrm()->
        esp_xmit()->
          esp_output_tail()->
            aead_request_set_callback(esp_output_done) <--[1]
            crypto_aead_encrypt()  <--[2]

In [1], .callback is set, and in [2] it will trigger the worker schedule,
later on a kernel thread will call .callback(esp_output_done), as the call
trace shows.

But in validate_xmit_xfrm():

  skb_list_walk_safe(skb, skb2, nskb) {
    ...
    err = x->type_offload->xmit(x, skb2, esp_features);  [esp_xmit]
    ...
  }

When the err is -EINPROGRESS, which means this skb2 will be enqueued and
later gets encrypted and sent out by .callback later in a kernel thread,
skb2 should be removed fromt skb chain. Otherwise, it will get processed
again outside validate_xmit_xfrm(), which could release skb secpath, and
cause the panic above.

This patch is to remove the skb from the chain when it's enqueued in
cryptd_wq. While at it, remove the unnecessary 'if (!skb)' check.

Fixes: 3dca3f38cfb8 ("xfrm: Separate ESP handling from segmentation for GRO packets.")
Reported-by: Xiumei Mu <xmu@redhat.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_device.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 3231ec628544..e2db468cf50e 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -78,8 +78,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 	int err;
 	unsigned long flags;
 	struct xfrm_state *x;
-	struct sk_buff *skb2, *nskb;
 	struct softnet_data *sd;
+	struct sk_buff *skb2, *nskb, *pskb = NULL;
 	netdev_features_t esp_features = features;
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sec_path *sp;
@@ -168,14 +168,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
 		} else {
 			if (skb == skb2)
 				skb = nskb;
-
-			if (!skb)
-				return NULL;
+			else
+				pskb->next = nskb;
 
 			continue;
 		}
 
 		skb_push(skb2, skb2->data - skb_mac_header(skb2));
+		pskb = skb2;
 	}
 
 	return skb;
-- 
2.17.1


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

* [PATCH 7/8] vti6: Fix memory leak of skb if input policy check fails
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
                   ` (5 preceding siblings ...)
  2020-03-27  8:10 ` [PATCH 6/8] esp: remove the skb from the chain when it's enqueued in cryptd_wq Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27  8:10 ` [PATCH 8/8] xfrm: policy: Fix doulbe free in xfrm_policy_timer Steffen Klassert
  2020-03-27 21:57 ` pull request (net): ipsec 2020-03-27 David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: Torsten Hilbrich <torsten.hilbrich@secunet.com>

The vti6_rcv function performs some tests on the retrieved tunnel
including checking the IP protocol, the XFRM input policy, the
source and destination address.

In all but one places the skb is released in the error case. When
the input policy check fails the network packet is leaked.

Using the same goto-label discard in this case to fix this problem.

Fixes: ed1efb2aefbb ("ipv6: Add support for IPsec virtual tunnel interfaces")
Signed-off-by: Torsten Hilbrich <torsten.hilbrich@secunet.com>
Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/ipv6/ip6_vti.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 56e642efefff..cc6180e08a4f 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb)
 
 		if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 			rcu_read_unlock();
-			return 0;
+			goto discard;
 		}
 
 		ipv6h = ipv6_hdr(skb);
-- 
2.17.1


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

* [PATCH 8/8] xfrm: policy: Fix doulbe free in xfrm_policy_timer
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
                   ` (6 preceding siblings ...)
  2020-03-27  8:10 ` [PATCH 7/8] vti6: Fix memory leak of skb if input policy check fails Steffen Klassert
@ 2020-03-27  8:10 ` Steffen Klassert
  2020-03-27 21:57 ` pull request (net): ipsec 2020-03-27 David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: Steffen Klassert @ 2020-03-27  8:10 UTC (permalink / raw)
  To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev

From: YueHaibing <yuehaibing@huawei.com>

After xfrm_add_policy add a policy, its ref is 2, then

                             xfrm_policy_timer
                               read_lock
                               xp->walk.dead is 0
                               ....
                               mod_timer()
xfrm_policy_kill
  policy->walk.dead = 1
  ....
  del_timer(&policy->timer)
    xfrm_pol_put //ref is 1
  xfrm_pol_put  //ref is 0
    xfrm_policy_destroy
      call_rcu
                                 xfrm_pol_hold //ref is 1
                               read_unlock
                               xfrm_pol_put //ref is 0
                                 xfrm_policy_destroy
                                  call_rcu

xfrm_policy_destroy is called twice, which may leads to
double free.

Call Trace:
RIP: 0010:refcount_warn_saturate+0x161/0x210
...
 xfrm_policy_timer+0x522/0x600
 call_timer_fn+0x1b3/0x5e0
 ? __xfrm_decode_session+0x2990/0x2990
 ? msleep+0xb0/0xb0
 ? _raw_spin_unlock_irq+0x24/0x40
 ? __xfrm_decode_session+0x2990/0x2990
 ? __xfrm_decode_session+0x2990/0x2990
 run_timer_softirq+0x5c5/0x10e0

Fix this by use write_lock_bh in xfrm_policy_kill.

Fixes: ea2dea9dacc2 ("xfrm: remove policy lock when accessing policy->walk.dead")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Acked-by: Timo Teräs <timo.teras@iki.fi>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
 net/xfrm/xfrm_policy.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 297d1eb79e5c..96a8c452b63e 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -434,7 +434,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy);
 
 static void xfrm_policy_kill(struct xfrm_policy *policy)
 {
+	write_lock_bh(&policy->lock);
 	policy->walk.dead = 1;
+	write_unlock_bh(&policy->lock);
 
 	atomic_inc(&policy->genid);
 
-- 
2.17.1


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

* Re: pull request (net): ipsec 2020-03-27
  2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
                   ` (7 preceding siblings ...)
  2020-03-27  8:10 ` [PATCH 8/8] xfrm: policy: Fix doulbe free in xfrm_policy_timer Steffen Klassert
@ 2020-03-27 21:57 ` David Miller
  8 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2020-03-27 21:57 UTC (permalink / raw)
  To: steffen.klassert; +Cc: herbert, netdev

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Fri, 27 Mar 2020 09:09:59 +0100

> 1) Handle NETDEV_UNREGISTER for xfrm device to handle asynchronous
>    unregister events cleanly. From Raed Salem.
> 
> 2) Fix vti6 tunnel inter address family TX through bpf_redirect().
>    From Nicolas Dichtel.
> 
> 3) Fix lenght check in verify_sec_ctx_len() to avoid a
>    slab-out-of-bounds. From Xin Long.
> 
> 4) Add a missing verify_sec_ctx_len check in xfrm_add_acquire
>    to avoid a possible out-of-bounds to access. From Xin Long.
> 
> 5) Use built-in RCU list checking of hlist_for_each_entry_rcu
>    to silence false lockdep warning in __xfrm6_tunnel_spi_lookup
>    when CONFIG_PROVE_RCU_LIST is enabled. From Madhuparna Bhowmik.
> 
> 6) Fix a panic on esp offload when crypto is done asynchronously.
>    From Xin Long.
> 
> 7) Fix a skb memory leak in an error path of vti6_rcv.
>    From Torsten Hilbrich.
> 
> 8) Fix a race that can lead to a doulbe free in xfrm_policy_timer.
>    From Xin Long.
> 
> Please pull or let me know if there are problems.

Pulled, thanks Steffen.

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

end of thread, other threads:[~2020-03-27 21:57 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-27  8:09 pull request (net): ipsec 2020-03-27 Steffen Klassert
2020-03-27  8:10 ` [PATCH 1/8] xfrm: handle NETDEV_UNREGISTER for xfrm device Steffen Klassert
2020-03-27  8:10 ` [PATCH 2/8] vti[6]: fix packet tx through bpf_redirect() in XinY cases Steffen Klassert
2020-03-27  8:10 ` [PATCH 3/8] xfrm: fix uctx len check in verify_sec_ctx_len Steffen Klassert
2020-03-27  8:10 ` [PATCH 4/8] xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire Steffen Klassert
2020-03-27  8:10 ` [PATCH 5/8] ipv6: xfrm6_tunnel.c: Use built-in RCU list checking Steffen Klassert
2020-03-27  8:10 ` [PATCH 6/8] esp: remove the skb from the chain when it's enqueued in cryptd_wq Steffen Klassert
2020-03-27  8:10 ` [PATCH 7/8] vti6: Fix memory leak of skb if input policy check fails Steffen Klassert
2020-03-27  8:10 ` [PATCH 8/8] xfrm: policy: Fix doulbe free in xfrm_policy_timer Steffen Klassert
2020-03-27 21:57 ` pull request (net): ipsec 2020-03-27 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.