Takashi Iwai 549579
From 3aff8aaca4e36dc8b17eaa011684881a80238966 Mon Sep 17 00:00:00 2001
Takashi Iwai 549579
From: Maxim Mikityanskiy <maxtram95@gmail.com>
Takashi Iwai 549579
Date: Wed, 5 Oct 2022 00:27:18 +0300
Takashi Iwai 549579
Subject: [PATCH] Bluetooth: L2CAP: Fix use-after-free caused by l2cap_reassemble_sdu
Takashi Iwai 549579
Git-commit: 3aff8aaca4e36dc8b17eaa011684881a80238966
Takashi Iwai 549579
Patch-mainline: v6.1-rc4
Takashi Iwai 549579
References: CVE-2022-3564 bsc#1206073
Takashi Iwai 549579
Takashi Iwai 549579
Fix the race condition between the following two flows that run in
Takashi Iwai 549579
Parallel: 
Takashi Iwai 549579
Takashi Iwai 549579
1. l2cap_reassemble_sdu -> chan->ops->recv (l2cap_sock_recv_cb) ->
Takashi Iwai 549579
   __sock_queue_rcv_skb.
Takashi Iwai 549579
Takashi Iwai 549579
2. bt_sock_recvmsg -> skb_recv_datagram, skb_free_datagram.
Takashi Iwai 549579
Takashi Iwai 549579
An SKB can be queued by the first flow and immediately dequeued and
Takashi Iwai 549579
freed by the second flow, therefore the callers of l2cap_reassemble_sdu
Takashi Iwai 549579
can't use the SKB after that function returns. However, some places
Takashi Iwai 549579
continue accessing struct l2cap_ctrl that resides in the SKB's CB for a
Takashi Iwai 549579
short time after l2cap_reassemble_sdu returns, leading to a
Takashi Iwai 549579
use-after-free condition (the stack trace is below, line numbers for
Takashi Iwai 549579
kernel 5.19.8).
Takashi Iwai 549579
Takashi Iwai 549579
Fix it by keeping a local copy of struct l2cap_ctrl.
Takashi Iwai 549579
Takashi Iwai 549579
Bug: KASAN: use-after-free in l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth
Takashi Iwai 549579
Read of size 1 at addr ffff88812025f2f0 by task kworker/u17:3/43169
Takashi Iwai 549579
Takashi Iwai 549579
Workqueue: hci0 hci_rx_work [bluetooth]
Takashi Iwai 549579
Call Trace:
Takashi Iwai 549579
 <TASK>
Takashi Iwai 549579
 dump_stack_lvl (lib/dump_stack.c:107 (discriminator 4))
Takashi Iwai 549579
 print_report.cold (mm/kasan/report.c:314 mm/kasan/report.c:429)
Takashi Iwai 549579
 ? l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth
Takashi Iwai 549579
 kasan_report (mm/kasan/report.c:162 mm/kasan/report.c:493)
Takashi Iwai 549579
 ? l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth
Takashi Iwai 549579
 l2cap_rx_state_recv (net/bluetooth/l2cap_core.c:6906) bluetooth
Takashi Iwai 549579
 l2cap_rx (net/bluetooth/l2cap_core.c:7236 net/bluetooth/l2cap_core.c:7271) bluetooth
Takashi Iwai 549579
 ret_from_fork (arch/x86/entry/entry_64.S:306)
Takashi Iwai 549579
 </TASK>
Takashi Iwai 549579
Takashi Iwai 549579
Allocated by task 43169:
Takashi Iwai 549579
 kasan_save_stack (mm/kasan/common.c:39)
Takashi Iwai 549579
 __kasan_slab_alloc (mm/kasan/common.c:45 mm/kasan/common.c:436 mm/kasan/common.c:469)
Takashi Iwai 549579
 kmem_cache_alloc_node (mm/slab.h:750 mm/slub.c:3243 mm/slub.c:3293)
Takashi Iwai 549579
 __alloc_skb (net/core/skbuff.c:414)
Takashi Iwai 549579
 l2cap_recv_frag (./include/net/bluetooth/bluetooth.h:425 net/bluetooth/l2cap_core.c:8329) bluetooth
Takashi Iwai 549579
 l2cap_recv_acldata (net/bluetooth/l2cap_core.c:8442) bluetooth
Takashi Iwai 549579
 hci_rx_work (net/bluetooth/hci_core.c:3642 net/bluetooth/hci_core.c:3832) bluetooth
Takashi Iwai 549579
 process_one_work (kernel/workqueue.c:2289)
Takashi Iwai 549579
 worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2437)
Takashi Iwai 549579
 kthread (kernel/kthread.c:376)
Takashi Iwai 549579
 ret_from_fork (arch/x86/entry/entry_64.S:306)
Takashi Iwai 549579
Takashi Iwai 549579
Freed by task 27920:
Takashi Iwai 549579
 kasan_save_stack (mm/kasan/common.c:39)
Takashi Iwai 549579
 kasan_set_track (mm/kasan/common.c:45)
Takashi Iwai 549579
 kasan_set_free_info (mm/kasan/generic.c:372)
Takashi Iwai 549579
 ____kasan_slab_free (mm/kasan/common.c:368 mm/kasan/common.c:328)
Takashi Iwai 549579
 slab_free_freelist_hook (mm/slub.c:1780)
Takashi Iwai 549579
 kmem_cache_free (mm/slub.c:3536 mm/slub.c:3553)
Takashi Iwai 549579
 skb_free_datagram (./include/net/sock.h:1578 ./include/net/sock.h:1639 net/core/datagram.c:323)
Takashi Iwai 549579
 bt_sock_recvmsg (net/bluetooth/af_bluetooth.c:295) bluetooth
Takashi Iwai 549579
 l2cap_sock_recvmsg (net/bluetooth/l2cap_sock.c:1212) bluetooth
Takashi Iwai 549579
 sock_read_iter (net/socket.c:1087)
Takashi Iwai 549579
 new_sync_read (./include/linux/fs.h:2052 fs/read_write.c:401)
Takashi Iwai 549579
 vfs_read (fs/read_write.c:482)
Takashi Iwai 549579
 ksys_read (fs/read_write.c:620)
Takashi Iwai 549579
 do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80)
Takashi Iwai 549579
 entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120)
Takashi Iwai 549579
Takashi Iwai 549579
Link: https://lore.kernel.org/linux-bluetooth/CAKErNvoqga1WcmoR3-0875esY6TVWFQDandbVZncSiuGPBQXLA@mail.gmail.com/T/#u
Takashi Iwai 549579
Fixes: d2a7ac5d5d3a ("Bluetooth: Add the ERTM receive state machine")
Takashi Iwai 549579
Fixes: 4b51dae96731 ("Bluetooth: Add streaming mode receive and incoming packet classifier")
Takashi Iwai 549579
Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
Takashi Iwai 549579
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Takashi Iwai 549579
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 549579
Takashi Iwai 549579
---
Takashi Iwai 549579
 net/bluetooth/l2cap_core.c |   48 ++++++++++++++++++++++++++++++++++++++-------
Takashi Iwai 549579
 1 file changed, 41 insertions(+), 7 deletions(-)
Takashi Iwai 549579
Takashi Iwai 549579
--- a/net/bluetooth/l2cap_core.c
Takashi Iwai 549579
+++ b/net/bluetooth/l2cap_core.c
Takashi Iwai 549579
@@ -6246,6 +6246,7 @@ static int l2cap_rx_state_recv(struct l2
Takashi Iwai 549579
 			       struct l2cap_ctrl *control,
Takashi Iwai 549579
 			       struct sk_buff *skb, u8 event)
Takashi Iwai 549579
 {
Takashi Iwai 549579
+	struct l2cap_ctrl local_control;
Takashi Iwai 549579
 	int err = 0;
Takashi Iwai 549579
 	bool skb_in_use = false;
Takashi Iwai 549579
 
Takashi Iwai 549579
@@ -6270,15 +6271,32 @@ static int l2cap_rx_state_recv(struct l2
Takashi Iwai 549579
 			chan->buffer_seq = chan->expected_tx_seq;
Takashi Iwai 549579
 			skb_in_use = true;
Takashi Iwai 549579
 
Takashi Iwai 549579
+			/* l2cap_reassemble_sdu may free skb, hence invalidate
Takashi Iwai 549579
+			 * control, so make a copy in advance to use it after
Takashi Iwai 549579
+			 * l2cap_reassemble_sdu returns and to avoid the race
Takashi Iwai 549579
+			 * condition, for example:
Takashi Iwai 549579
+			 *
Takashi Iwai 549579
+			 * The current thread calls:
Takashi Iwai 549579
+			 *   l2cap_reassemble_sdu
Takashi Iwai 549579
+			 *     chan->ops->recv == l2cap_sock_recv_cb
Takashi Iwai 549579
+			 *       __sock_queue_rcv_skb
Takashi Iwai 549579
+			 * Another thread calls:
Takashi Iwai 549579
+			 *   bt_sock_recvmsg
Takashi Iwai 549579
+			 *     skb_recv_datagram
Takashi Iwai 549579
+			 *     skb_free_datagram
Takashi Iwai 549579
+			 * Then the current thread tries to access control, but
Takashi Iwai 549579
+			 * it was freed by skb_free_datagram.
Takashi Iwai 549579
+			 */
Takashi Iwai 549579
+			local_control = *control;
Takashi Iwai 549579
 			err = l2cap_reassemble_sdu(chan, skb, control);
Takashi Iwai 549579
 			if (err)
Takashi Iwai 549579
 				break;
Takashi Iwai 549579
 
Takashi Iwai 549579
-			if (control->final) {
Takashi Iwai 549579
+			if (local_control.final) {
Takashi Iwai 549579
 				if (!test_and_clear_bit(CONN_REJ_ACT,
Takashi Iwai 549579
 							&chan->conn_state)) {
Takashi Iwai 549579
-					control->final = 0;
Takashi Iwai 549579
-					l2cap_retransmit_all(chan, control);
Takashi Iwai 549579
+					local_control.final = 0;
Takashi Iwai 549579
+					l2cap_retransmit_all(chan, &local_control);
Takashi Iwai 549579
 					l2cap_ertm_send(chan);
Takashi Iwai 549579
 				}
Takashi Iwai 549579
 			}
Takashi Iwai 549579
@@ -6658,11 +6676,27 @@ static int l2cap_rx(struct l2cap_chan *c
Takashi Iwai 549579
 static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
Takashi Iwai 549579
 			   struct sk_buff *skb)
Takashi Iwai 549579
 {
Takashi Iwai 549579
+	/* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
Takashi Iwai 549579
+	 * the txseq field in advance to use it after l2cap_reassemble_sdu
Takashi Iwai 549579
+	 * returns and to avoid the race condition, for example:
Takashi Iwai 549579
+	 *
Takashi Iwai 549579
+	 * The current thread calls:
Takashi Iwai 549579
+	 *   l2cap_reassemble_sdu
Takashi Iwai 549579
+	 *     chan->ops->recv == l2cap_sock_recv_cb
Takashi Iwai 549579
+	 *       __sock_queue_rcv_skb
Takashi Iwai 549579
+	 * Another thread calls:
Takashi Iwai 549579
+	 *   bt_sock_recvmsg
Takashi Iwai 549579
+	 *     skb_recv_datagram
Takashi Iwai 549579
+	 *     skb_free_datagram
Takashi Iwai 549579
+	 * Then the current thread tries to access control, but it was freed by
Takashi Iwai 549579
+	 * skb_free_datagram.
Takashi Iwai 549579
+	 */
Takashi Iwai 549579
+	u16 txseq = control->txseq;
Takashi Iwai 549579
+
Takashi Iwai 549579
 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
Takashi Iwai 549579
 	       chan->rx_state);
Takashi Iwai 549579
 
Takashi Iwai 549579
-	if (l2cap_classify_txseq(chan, control->txseq) ==
Takashi Iwai 549579
-	    L2CAP_TXSEQ_EXPECTED) {
Takashi Iwai 549579
+	if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
Takashi Iwai 549579
 		l2cap_pass_to_tx(chan, control);
Takashi Iwai 549579
 
Takashi Iwai 549579
 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
Takashi Iwai 549579
@@ -6685,8 +6719,8 @@ static int l2cap_stream_rx(struct l2cap_
Takashi Iwai 549579
 		}
Takashi Iwai 549579
 	}
Takashi Iwai 549579
 
Takashi Iwai 549579
-	chan->last_acked_seq = control->txseq;
Takashi Iwai 549579
-	chan->expected_tx_seq = __next_seq(chan, control->txseq);
Takashi Iwai 549579
+	chan->last_acked_seq = txseq;
Takashi Iwai 549579
+	chan->expected_tx_seq = __next_seq(chan, txseq);
Takashi Iwai 549579
 
Takashi Iwai 549579
 	return 0;
Takashi Iwai 549579
 }