From nobody Fri Sep 25 04:08:10 2026 Received: from mail-wm2-f12.google.com (mail-wm2-f12.google.com [74.125.225.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34EDC439351 for ; Wed, 16 Sep 2026 19:35:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789587321; cv=none; b=efScOZY9cXZC7CFq2wzXWCLVq+3q7BbsfwXhiUo0v3p69p3Kh8vKbIg5923zrxWG71LGkIHAjdP3hDWOjiiF/r9AmaZdfl1NoySiI9Zy/3dVlSTaBMf3ebVzwQIuLgivVGwj+y4ncrs9VcWUDkW4qmgDTwQHaq9m/4uPhlX2B7g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789587321; c=relaxed/simple; bh=37mrbgiKj2yMEYJvYaqXJn4UZXI1sNe0ef9mvGAtKg4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MH1SiQ5aXa6DuK+aV+Nl6UNslLG7MFjl6jhfI63so6m3oNopjo5reFm5w4JgUnLdCCca/6D5hYAHFRmYfS8FmpS5lDFfC9VdSd7JOFJcOn5JZE7f/HzC15QVIQMUeLGv9GHq2lnFqPvMvq9DEVRZy1BmFIQyUcJcSh5TEEQLKqg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Imrncc03; arc=none smtp.client-ip=74.125.225.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Imrncc03" Received: by mail-wm2-f12.google.com with SMTP id 5b1f17b1804b1-49ccfd61ecaso934655e9.3 for ; Wed, 16 Sep 2026 12:35:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789587312; x=1790192112; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=713Rnd8tXfX5v2C5/tcwaMUXoXj1OqEgNCWH9P2bUyg=; b=Imrncc0329czpyqr4TvUHme6UIf+AkGGV97e8rqkezAHC12n3V9ZuC3IF+UrGEfLAU Xd+8qL1bqsG0AXYgfcofro6Schh/WZco+B4TgF/+FqHWZP+J7XGJ/+cZVCNv10UrXvWG pYmy6lECGzMjhAsDPHvVpA6UCz72kjjGolj1+I1Zbmtn5BFmi9KllofD+LYCAPYm+BKY 2Z5LUZmToNhRcjrWCPK0kkCqw6j+7S7vlhf9iPtVzA3zl4uUfT91bZhLxessca4UYTIY Dh/aUdOAlxh+GGBgcizqkWi3Hoz70VClkKhqxQsZEdTowvKzN0Jo7D46UKMlwL/CfQ/k NIkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789587312; x=1790192112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=713Rnd8tXfX5v2C5/tcwaMUXoXj1OqEgNCWH9P2bUyg=; b=dy2jdzuFWmtjqKTrcxLxT3zL8eazoL7aHpfoHTD/tWzc3vce8Qw0Z4ahEGnHy1uMpU RGFXFyTZKhcKJtKuk3LYGDIUEeT0uLtLeDvM6kcMhKqPtqwzharUg+NvxAOJyEdjFcWC 0hRCD+n5tGoh34C7bl0MeG4dBx2VVHRsVY30CeT2Q0Xag+J0oVUGMXwcYeQe0cZq23o1 T8US1KbYcxr8nDuzH7n75jxqqzErSF+gJVpQBIBHtMZjylUzrj1ycrBlR0KJv/ggUb9n 9jKlw+DwPt6e11qsNH51uIZcYRETu1wk/OnLYx+a3tG+uMjXFI2RApGgiSDlcY4YhyES HOvQ== X-Forwarded-Encrypted: i=1; AKwUvByVPGwGIzYPkBBkj3ClZEweuSmES4W0jPTlDB8R7sePcSrb6PaDlL8nt1OpZJadU8MuUz4+gHuX/Dji6rc=@vger.kernel.org X-Gm-Message-State: AFuF++lSELEKwXyYshuvcqn59a2V6II3ZJaZa/TuDeadBSzgAgKl0jjb 1YJec9ylKS/8oohVPqLMSLQg1wytkvugETOBNg6LvYCgWK6OeJUJ7FoP X-Gm-Gg: AYBFou3eOWeLnXnxSA/WfuepapwI2XulVwW+99+gZBXAjHWQzF1AbQ9ePG/F3L6ODzs n93i8lGjqcJjuxrVLUrsHNMPNoDyEkNlUtHs0EUujKj7pstC5Q3haYfhq+0Tkgq7hV9eI3W1X4r wZTxTP2xvhVmWYMfQaU3rTXWLUTPTLUoJhp7/UUKGzo0lik16EAZZPUn6gi4AisJy6KaJqIGuGQ x7velamGL9Y3bo5qxWRtftG7H6R0nSjxSWSce4dYlfh65Zz8yVd5O+mBM7pJXxaESNx+Rg4ZbTw a6/2yuSgpFPFib9huPl9ygTu9+pxzvzhv3chqtJCAvkO9fujyxc89CJ4a8ortvYpXiUNUm/Jycx av4fW7RaE4MpXwEGo0xHsa3ACDKHeUfwFwj9JkNZhq9Y1BBaLCDCoxoJ219KRwFv+arAT00mAkn RbBE4ZQeyMFQCBm1ag6C5NPCn7b0Tajfik5W32CHO69v5Rs87BOyy7iVaXc+TMLf8g6YtONY+zK q/6tekhbVocT8mwJgGww0CHwTNXmklRJ8tTWx5Jr0doTotmNJ8bAux12w5lUuTi6tpixRHlgYHL aBlIvlkO9pWTBgLGRi7/7/FZF8zbUuVxD4FiCOZVBzxKA2Y/1WPUhHGubIFM6uMMNgDRgIMNKaF qWsPdcfCkBvhVVcG7 X-Received: by 2002:a05:600c:46d1:b0:49c:c0d4:53d9 with SMTP id 5b1f17b1804b1-49eb72fbf26mr45934875e9.14.1789587311636; Wed, 16 Sep 2026 12:35:11 -0700 (PDT) Received: from MacBook-Pro-von-Karl.localdomain (dynamic-2a02-3100-adf7-5a01-5cac-d7ee-c105-a566.310.pool.telefonica.de. [2a02:3100:adf7:5a01:5cac:d7ee:c105:a566]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49e847fcbdfsm60879335e9.4.2026.09.16.12.35.09 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 16 Sep 2026 12:35:10 -0700 (PDT) From: Karl Mehltretter To: stable@vger.kernel.org Cc: Karl Mehltretter , gregkh@linuxfoundation.org, sashal@kernel.org, luiz.dentz@gmail.com, luiz.von.dentz@intel.com, marcel@holtmann.org, johan.hedberg@gmail.com, eadavis@qq.com, davem@davemloft.net, kuba@kernel.org, linux-bluetooth@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, patches@lists.linux.dev, syzbot+b7f6f8c9303466e16c8a@syzkaller.appspotmail.com Subject: [PATCH 5.10.y] Bluetooth: L2CAP: Fix deadlock Date: Wed, 16 Sep 2026 21:34:54 +0200 Message-Id: <20260916193454.9996-1-kmehltretter@gmail.com> X-Mailer: git-send-email 2.39.5 (Apple Git-154) In-Reply-To: References: <2026091453-unwary-delete-b272@gregkh> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Luiz Augusto von Dentz [ Upstream commit f1a8f402f13f94263cf349216c257b2985100927 ] This fixes the following deadlock introduced by 39a92a55be13 ("bluetooth/l2cap: sync sock recv cb and release") =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D WARNING: possible recursive locking detected 6.10.0-rc3-g4029dba6b6f1 #6823 Not tainted -------------------------------------------- kworker/u5:0/35 is trying to acquire lock: ffff888002ec2510 (&chan->lock#2/1){+.+.}-{3:3}, at: l2cap_sock_recv_cb+0x44/0x1e0 but task is already holding lock: ffff888002ec2510 (&chan->lock#2/1){+.+.}-{3:3}, at: l2cap_get_chan_by_scid+0xaf/0xd0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&chan->lock#2/1); lock(&chan->lock#2/1); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by kworker/u5:0/35: #0: ffff888002b8a940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: process_one_work+0x750/0x930 #1: ffff888002c67dd0 ((work_completion)(&hdev->rx_work)){+.+.}-{0:0}, at: process_one_work+0x44e/0x930 #2: ffff888002ec2510 (&chan->lock#2/1){+.+.}-{3:3}, at: l2cap_get_chan_by_scid+0xaf/0xd0 To fix the original problem this introduces l2cap_chan_lock at l2cap_conless_channel to ensure that l2cap_sock_recv_cb is called with chan->lock held. Fixes: 89e856e124f9 ("bluetooth/l2cap: sync sock recv cb and release") Signed-off-by: Luiz Augusto von Dentz [ Karl Mehltretter: only the l2cap_core.c and l2cap_sock.c hunks apply to this tree. hci_sync.c and hci_sync.h do not exist here, and the hci_core.c change is an unrelated conversion of hci_dev_cmd() off the old hci_request API. The changes to both L2CAP files apply unmodified. The lock this adds to l2cap_conless_channel() is also the one that commit c531e63871c0 ("Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()") was backported without, so it additionally pairs the l2cap_chan_unlock() that function currently calls on a mutex it never acquired. ] Assisted-by: LLM Signed-off-by: Karl Mehltretter --- Notes: This is intended to replace the queued revert of commit 2243127db6ba ("bluetooth/l2cap: sync sock recv cb and release"), rather than to be applied on top of it. =20 The revert fixes the deadlock but removes the NULL guard from l2cap_sock_recv_cb(), while l2cap_sock_destruct() still sets chan->data= to NULL. Under KASAN, closing receiving sockets while L2CAP data is inbou= nd then gives a fatal NULL dereference in hci_rx_work, reproduced 3/3 on v5.10.270 with the queued revert applied. This patch keeps the guard a= nd fixes the deadlock in one step, and uses the two applicable upstream L2CAP hunks unmodified. =20 Tested in QEMU with two virtual BR/EDR controllers, PROVE_LOCKING, DEBUG_MUTEXES and KASAN: =20 v5.10.270 as released recursive chan->lock deadlock v5.10.270 + the queued revert fatal NULL deref, 3/3 v5.10.270 + this patch clean 3/3, 300 close cycles each =20 BlueZ's own l2cap-tester also deadlocks hci_rx_work on v5.10.270 and ne= ver completes. With this patch all six tester suites run to completion. =20 Also on a Raspberry Pi 400 (BCM2711, onboard CYW43455) with a second bo= ard as the L2CAP peer, each test from its own boot so lockdep was armed for each: =20 v5.10.270 as released, connectionless bad unlock balance v5.10.270 as released, connected possible recursive locking v5.10.270 + this patch, connectionless clean, debug_locks still 1 v5.10.270 + this patch, connected clean, debug_locks still 1 =20 The same board with an A2DP speaker shows the user-visible effect. On v5.10.270 as released, connecting to the speaker deadlocks hci_rx_work = and playback cannot start at all: =20 bluetoothd: a2dp-source profile connect failed: Device or resource bu= sy =20 task:kworker/u9:0 state:D Workqueue: hci0 hci_rx_work [bluetooth] __mutex_lock l2cap_sock_recv_cb l2cap_recv_frame l2cap_recv_acldata hci_rx_work =20 With this patch the same speaker connects and plays the full track with= no kernel warning and debug_locks still 1. =20 If the queued revert is kept instead, the same end state is reachable w= ith two patches on top of it, which I can send. net/bluetooth/l2cap_core.c | 3 +++ net/bluetooth/l2cap_sock.c | 13 +------------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1122566c4b50..7de512843f06 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -8044,6 +8044,8 @@ static void l2cap_conless_channel(struct l2cap_conn *= conn, __le16 psm, =20 BT_DBG("chan %p, len %d", chan, skb->len); =20 + l2cap_chan_lock(chan); + if (chan->state !=3D BT_BOUND && chan->state !=3D BT_CONNECTED) goto drop; =20 @@ -8061,6 +8063,7 @@ static void l2cap_conless_channel(struct l2cap_conn *= conn, __le16 psm, } =20 drop: + l2cap_chan_unlock(chan); l2cap_chan_put(chan); free_skb: kfree_skb(skb); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9d834f225462..018b5a0c87ce 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1548,18 +1548,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *cha= n, struct sk_buff *skb) struct l2cap_pinfo *pi; int err; =20 - /* To avoid race with sock_release, a chan lock needs to be added here - * to synchronize the sock. - */ - l2cap_chan_hold(chan); - l2cap_chan_lock(chan); sk =3D chan->data; - - if (!sk) { - l2cap_chan_unlock(chan); - l2cap_chan_put(chan); + if (!sk) return -ENXIO; - } =20 pi =3D l2cap_pi(sk); lock_sock(sk); @@ -1611,8 +1602,6 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan= , struct sk_buff *skb) =20 done: release_sock(sk); - l2cap_chan_unlock(chan); - l2cap_chan_put(chan); =20 return err; } base-commit: 1797d8bf8d0c2e74defad605d14e3553d43a3caf --=20 2.53.0