All of lore.kernel.org
 help / color / mirror / Atom feed
* pull-request: can 2021-06-19
@ 2021-06-19 22:01 Marc Kleine-Budde
  2021-06-19 22:01 ` [net 1/5] can: bcm: delay release of struct bcm_op after synchronize_rcu() Marc Kleine-Budde
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-06-19 22:01 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, linux-can, kernel

Hello Jakub, hello David,

this is a pull request of 5 patches for net/master.

The first patch is by Thadeu Lima de Souza Cascardo and fixes a
potential use-after-free in the CAN broadcast manager socket, by
delaying the release of struct bcm_op after synchronize_rcu().

Oliver Hartkopp's patch fixes a similar potential user-after-free in
the CAN gateway socket by synchronizing RCU operations before removing
gw job entry.

Another patch by Oliver Hartkopp fixes a potential use-after-free in
the ISOTP socket by omitting unintended hrtimer restarts on socket
release.

Oleksij Rempel's patch for the j1939 socket fixes a potential
use-after-free by setting the SOCK_RCU_FREE flag on the socket.

The last patch is by Pavel Skripkin and fixes a use-after-free in the
ems_usb CAN driver.

All patches are intended for stable and have stable@v.k.o on Cc.

regards,
Marc

---

The following changes since commit dda2626b86c2c1813b7bfdd10d2fdd849611fc97:

  Merge branch 'ezchip-fixes' (2021-06-19 11:46:24 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git tags/linux-can-fixes-for-5.13-20210619

for you to fetch changes up to ab4a0b8fcb9a95c02909b62049811bd2e586aaa4:

  net: can: ems_usb: fix use-after-free in ems_usb_disconnect() (2021-06-19 23:54:00 +0200)

----------------------------------------------------------------
linux-can-fixes-for-5.13-20210619

----------------------------------------------------------------
Oleksij Rempel (1):
      can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after RCU is done

Oliver Hartkopp (2):
      can: gw: synchronize rcu operations before removing gw job entry
      can: isotp: isotp_release(): omit unintended hrtimer restart on socket release

Pavel Skripkin (1):
      net: can: ems_usb: fix use-after-free in ems_usb_disconnect()

Thadeu Lima de Souza Cascardo (1):
      can: bcm: delay release of struct bcm_op after synchronize_rcu()

 drivers/net/can/usb/ems_usb.c | 3 ++-
 net/can/bcm.c                 | 7 ++++++-
 net/can/gw.c                  | 3 +++
 net/can/isotp.c               | 7 ++++---
 net/can/j1939/main.c          | 4 ++++
 net/can/j1939/socket.c        | 3 +++
 6 files changed, 22 insertions(+), 5 deletions(-)




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

* [net 1/5] can: bcm: delay release of struct bcm_op after synchronize_rcu()
  2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
@ 2021-06-19 22:01 ` Marc Kleine-Budde
  2021-06-19 22:01 ` [net 2/5] can: gw: synchronize rcu operations before removing gw job entry Marc Kleine-Budde
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-06-19 22:01 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Thadeu Lima de Souza Cascardo,
	linux-stable, syzbot+0f7e7e5e2f4f40fa89c0, Norbert Slusarek,
	Oliver Hartkopp, Marc Kleine-Budde

From: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>

can_rx_register() callbacks may be called concurrently to the call to
can_rx_unregister(). The callbacks and callback data, though, are
protected by RCU and the struct sock reference count.

So the callback data is really attached to the life of sk, meaning
that it should be released on sk_destruct. However, bcm_remove_op()
calls tasklet_kill(), and RCU callbacks may be called under RCU
softirq, so that cannot be used on kernels before the introduction of
HRTIMER_MODE_SOFT.

However, bcm_rx_handler() is called under RCU protection, so after
calling can_rx_unregister(), we may call synchronize_rcu() in order to
wait for any RCU read-side critical sections to finish. That is,
bcm_rx_handler() won't be called anymore for those ops. So, we only
free them, after we do that synchronize_rcu().

Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Link: https://lore.kernel.org/r/20210619161813.2098382-1-cascardo@canonical.com
Cc: linux-stable <stable@vger.kernel.org>
Reported-by: syzbot+0f7e7e5e2f4f40fa89c0@syzkaller.appspotmail.com
Reported-by: Norbert Slusarek <nslusarek@gmx.net>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 net/can/bcm.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/can/bcm.c b/net/can/bcm.c
index f3e4d9528fa3..0928a39c4423 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -785,6 +785,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
 						  bcm_rx_handler, op);
 
 			list_del(&op->list);
+			synchronize_rcu();
 			bcm_remove_op(op);
 			return 1; /* done */
 		}
@@ -1533,9 +1534,13 @@ static int bcm_release(struct socket *sock)
 					  REGMASK(op->can_id),
 					  bcm_rx_handler, op);
 
-		bcm_remove_op(op);
 	}
 
+	synchronize_rcu();
+
+	list_for_each_entry_safe(op, next, &bo->rx_ops, list)
+		bcm_remove_op(op);
+
 #if IS_ENABLED(CONFIG_PROC_FS)
 	/* remove procfs entry */
 	if (net->can.bcmproc_dir && bo->bcm_proc_read)

base-commit: dda2626b86c2c1813b7bfdd10d2fdd849611fc97
-- 
2.30.2



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

* [net 2/5] can: gw: synchronize rcu operations before removing gw job entry
  2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
  2021-06-19 22:01 ` [net 1/5] can: bcm: delay release of struct bcm_op after synchronize_rcu() Marc Kleine-Budde
@ 2021-06-19 22:01 ` Marc Kleine-Budde
  2021-06-19 22:01 ` [net 3/5] can: isotp: isotp_release(): omit unintended hrtimer restart on socket release Marc Kleine-Budde
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-06-19 22:01 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, linux-stable,
	Marc Kleine-Budde

From: Oliver Hartkopp <socketcan@hartkopp.net>

can_can_gw_rcv() is called under RCU protection, so after calling
can_rx_unregister(), we have to call synchronize_rcu in order to wait
for any RCU read-side critical sections to finish before removing the
kmem_cache entry with the referenced gw job entry.

Link: https://lore.kernel.org/r/20210618173645.2238-1-socketcan@hartkopp.net
Fixes: c1aabdf379bc ("can-gw: add netlink based CAN routing")
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 net/can/gw.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/can/gw.c b/net/can/gw.c
index ba4124805602..d8861e862f15 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -596,6 +596,7 @@ static int cgw_notifier(struct notifier_block *nb,
 			if (gwj->src.dev == dev || gwj->dst.dev == dev) {
 				hlist_del(&gwj->list);
 				cgw_unregister_filter(net, gwj);
+				synchronize_rcu();
 				kmem_cache_free(cgw_cache, gwj);
 			}
 		}
@@ -1154,6 +1155,7 @@ static void cgw_remove_all_jobs(struct net *net)
 	hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) {
 		hlist_del(&gwj->list);
 		cgw_unregister_filter(net, gwj);
+		synchronize_rcu();
 		kmem_cache_free(cgw_cache, gwj);
 	}
 }
@@ -1222,6 +1224,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 		hlist_del(&gwj->list);
 		cgw_unregister_filter(net, gwj);
+		synchronize_rcu();
 		kmem_cache_free(cgw_cache, gwj);
 		err = 0;
 		break;
-- 
2.30.2



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

* [net 3/5] can: isotp: isotp_release(): omit unintended hrtimer restart on socket release
  2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
  2021-06-19 22:01 ` [net 1/5] can: bcm: delay release of struct bcm_op after synchronize_rcu() Marc Kleine-Budde
  2021-06-19 22:01 ` [net 2/5] can: gw: synchronize rcu operations before removing gw job entry Marc Kleine-Budde
@ 2021-06-19 22:01 ` Marc Kleine-Budde
  2021-06-19 22:01 ` [net 4/5] can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after RCU is done Marc Kleine-Budde
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-06-19 22:01 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Oliver Hartkopp, linux-stable,
	Marc Kleine-Budde

From: Oliver Hartkopp <socketcan@hartkopp.net>

When closing the isotp socket, the potentially running hrtimers are
canceled before removing the subscription for CAN identifiers via
can_rx_unregister().

This may lead to an unintended (re)start of a hrtimer in
isotp_rcv_cf() and isotp_rcv_fc() in the case that a CAN frame is
received by isotp_rcv() while the subscription removal is processed.

However, isotp_rcv() is called under RCU protection, so after calling
can_rx_unregister, we may call synchronize_rcu in order to wait for
any RCU read-side critical sections to finish. This prevents the
reception of CAN frames after hrtimer_cancel() and therefore the
unintended (re)start of the hrtimers.

Link: https://lore.kernel.org/r/20210618173713.2296-1-socketcan@hartkopp.net
Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol")
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 net/can/isotp.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/can/isotp.c b/net/can/isotp.c
index be6183f8ca11..234cc4ad179a 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -1028,9 +1028,6 @@ static int isotp_release(struct socket *sock)
 
 	lock_sock(sk);
 
-	hrtimer_cancel(&so->txtimer);
-	hrtimer_cancel(&so->rxtimer);
-
 	/* remove current filters & unregister */
 	if (so->bound && (!(so->opt.flags & CAN_ISOTP_SF_BROADCAST))) {
 		if (so->ifindex) {
@@ -1042,10 +1039,14 @@ static int isotp_release(struct socket *sock)
 						  SINGLE_MASK(so->rxid),
 						  isotp_rcv, sk);
 				dev_put(dev);
+				synchronize_rcu();
 			}
 		}
 	}
 
+	hrtimer_cancel(&so->txtimer);
+	hrtimer_cancel(&so->rxtimer);
+
 	so->ifindex = 0;
 	so->bound = 0;
 
-- 
2.30.2



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

* [net 4/5] can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after RCU is done
  2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2021-06-19 22:01 ` [net 3/5] can: isotp: isotp_release(): omit unintended hrtimer restart on socket release Marc Kleine-Budde
@ 2021-06-19 22:01 ` Marc Kleine-Budde
  2021-06-19 22:01 ` [net 5/5] net: can: ems_usb: fix use-after-free in ems_usb_disconnect() Marc Kleine-Budde
  2021-06-21 19:50 ` pull-request: can 2021-06-19 patchwork-bot+netdevbpf
  5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-06-19 22:01 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Oleksij Rempel, linux-stable,
	Thadeu Lima de Souza Cascardo, syzbot+bdf710cfc41c186fdff3,
	Marc Kleine-Budde

From: Oleksij Rempel <o.rempel@pengutronix.de>

Set SOCK_RCU_FREE to let RCU to call sk_destruct() on completion.
Without this patch, we will run in to j1939_can_recv() after priv was
freed by j1939_sk_release()->j1939_sk_sock_destruct()

Fixes: 25fe97cb7620 ("can: j1939: move j1939_priv_put() into sk_destruct callback")
Link: https://lore.kernel.org/r/20210617130623.12705-1-o.rempel@pengutronix.de
Cc: linux-stable <stable@vger.kernel.org>
Reported-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Reported-by: syzbot+bdf710cfc41c186fdff3@syzkaller.appspotmail.com
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 net/can/j1939/main.c   | 4 ++++
 net/can/j1939/socket.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
index da3a7a7bcff2..08c8606cfd9c 100644
--- a/net/can/j1939/main.c
+++ b/net/can/j1939/main.c
@@ -193,6 +193,10 @@ static void j1939_can_rx_unregister(struct j1939_priv *priv)
 	can_rx_unregister(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
 			  j1939_can_recv, priv);
 
+	/* The last reference of priv is dropped by the RCU deferred
+	 * j1939_sk_sock_destruct() of the last socket, so we can
+	 * safely drop this reference here.
+	 */
 	j1939_priv_put(priv);
 }
 
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index 56aa66147d5a..fce8bc8afeb7 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -398,6 +398,9 @@ static int j1939_sk_init(struct sock *sk)
 	atomic_set(&jsk->skb_pending, 0);
 	spin_lock_init(&jsk->sk_session_queue_lock);
 	INIT_LIST_HEAD(&jsk->sk_session_queue);
+
+	/* j1939_sk_sock_destruct() depends on SOCK_RCU_FREE flag */
+	sock_set_flag(sk, SOCK_RCU_FREE);
 	sk->sk_destruct = j1939_sk_sock_destruct;
 	sk->sk_protocol = CAN_J1939;
 
-- 
2.30.2



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

* [net 5/5] net: can: ems_usb: fix use-after-free in ems_usb_disconnect()
  2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2021-06-19 22:01 ` [net 4/5] can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after RCU is done Marc Kleine-Budde
@ 2021-06-19 22:01 ` Marc Kleine-Budde
  2021-06-21 19:50 ` pull-request: can 2021-06-19 patchwork-bot+netdevbpf
  5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2021-06-19 22:01 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, linux-can, kernel, Pavel Skripkin, linux-stable,
	Marc Kleine-Budde

From: Pavel Skripkin <paskripkin@gmail.com>

In ems_usb_disconnect() dev pointer, which is netdev private data, is
used after free_candev() call:
| 	if (dev) {
| 		unregister_netdev(dev->netdev);
| 		free_candev(dev->netdev);
|
| 		unlink_all_urbs(dev);
|
| 		usb_free_urb(dev->intr_urb);
|
| 		kfree(dev->intr_in_buffer);
| 		kfree(dev->tx_msg_buffer);
| 	}

Fix it by simply moving free_candev() at the end of the block.

Fail log:
| BUG: KASAN: use-after-free in ems_usb_disconnect
| Read of size 8 at addr ffff88804e041008 by task kworker/1:2/2895
|
| CPU: 1 PID: 2895 Comm: kworker/1:2 Not tainted 5.13.0-rc5+ #164
| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a-rebuilt.opensuse.4
| Workqueue: usb_hub_wq hub_event
| Call Trace:
|     dump_stack (lib/dump_stack.c:122)
|     print_address_description.constprop.0.cold (mm/kasan/report.c:234)
|     kasan_report.cold (mm/kasan/report.c:420 mm/kasan/report.c:436)
|     ems_usb_disconnect (drivers/net/can/usb/ems_usb.c:683 drivers/net/can/usb/ems_usb.c:1058)

Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
Link: https://lore.kernel.org/r/20210617185130.5834-1-paskripkin@gmail.com
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/usb/ems_usb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 5af69787d9d5..0a37af4a3fa4 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -1053,7 +1053,6 @@ static void ems_usb_disconnect(struct usb_interface *intf)
 
 	if (dev) {
 		unregister_netdev(dev->netdev);
-		free_candev(dev->netdev);
 
 		unlink_all_urbs(dev);
 
@@ -1061,6 +1060,8 @@ static void ems_usb_disconnect(struct usb_interface *intf)
 
 		kfree(dev->intr_in_buffer);
 		kfree(dev->tx_msg_buffer);
+
+		free_candev(dev->netdev);
 	}
 }
 
-- 
2.30.2



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

* Re: pull-request: can 2021-06-19
  2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2021-06-19 22:01 ` [net 5/5] net: can: ems_usb: fix use-after-free in ems_usb_disconnect() Marc Kleine-Budde
@ 2021-06-21 19:50 ` patchwork-bot+netdevbpf
  5 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2021-06-21 19:50 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: netdev, davem, kuba, linux-can, kernel

Hello:

This pull request was applied to netdev/net.git (refs/heads/master):

On Sun, 20 Jun 2021 00:01:10 +0200 you wrote:
> Hello Jakub, hello David,
> 
> this is a pull request of 5 patches for net/master.
> 
> The first patch is by Thadeu Lima de Souza Cascardo and fixes a
> potential use-after-free in the CAN broadcast manager socket, by
> delaying the release of struct bcm_op after synchronize_rcu().
> 
> [...]

Here is the summary with links:
  - pull-request: can 2021-06-19
    https://git.kernel.org/netdev/net/c/d52f9b22d56f
  - [net,2/5] can: gw: synchronize rcu operations before removing gw job entry
    https://git.kernel.org/netdev/net/c/fb8696ab14ad
  - [net,3/5] can: isotp: isotp_release(): omit unintended hrtimer restart on socket release
    https://git.kernel.org/netdev/net/c/14a4696bc311
  - [net,4/5] can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after RCU is done
    https://git.kernel.org/netdev/net/c/22c696fed25c
  - [net,5/5] net: can: ems_usb: fix use-after-free in ems_usb_disconnect()
    https://git.kernel.org/netdev/net/c/ab4a0b8fcb9a

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2021-06-21 19:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-19 22:01 pull-request: can 2021-06-19 Marc Kleine-Budde
2021-06-19 22:01 ` [net 1/5] can: bcm: delay release of struct bcm_op after synchronize_rcu() Marc Kleine-Budde
2021-06-19 22:01 ` [net 2/5] can: gw: synchronize rcu operations before removing gw job entry Marc Kleine-Budde
2021-06-19 22:01 ` [net 3/5] can: isotp: isotp_release(): omit unintended hrtimer restart on socket release Marc Kleine-Budde
2021-06-19 22:01 ` [net 4/5] can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after RCU is done Marc Kleine-Budde
2021-06-19 22:01 ` [net 5/5] net: can: ems_usb: fix use-after-free in ems_usb_disconnect() Marc Kleine-Budde
2021-06-21 19:50 ` pull-request: can 2021-06-19 patchwork-bot+netdevbpf

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.