From nobody Thu Apr 9 12:48:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5E264C43217 for ; Mon, 10 Oct 2022 07:05:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231555AbiJJHFP (ORCPT ); Mon, 10 Oct 2022 03:05:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231416AbiJJHEs (ORCPT ); Mon, 10 Oct 2022 03:04:48 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A320052E61; Mon, 10 Oct 2022 00:04:27 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 6069CB80E54; Mon, 10 Oct 2022 07:04:25 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD8F1C433D6; Mon, 10 Oct 2022 07:04:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1665385464; bh=9TaVU9acwI902OnE6elPW0nf4T3kB68NpMHKm/VssLs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1S8N2lZM53YkviKs/uF27Y3bYCEBFfelcclRChyrsmypg6sMF5KGBr77GpZUYaGoO aKHobOtsQrQlQcq7YcNxlR6a0fz8IecS/++4n8lmRZnpXqUMCCEzrc4KnMW3oEkdSL SWmCpds7fo/KchTH59m7fkN2Mw3lSdANM2loGi44= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, syzbot , Tetsuo Handa , Luiz Augusto von Dentz Subject: [PATCH 6.0 17/17] Bluetooth: use hdev->workqueue when queuing hdev->{cmd,ncmd}_timer works Date: Mon, 10 Oct 2022 09:04:40 +0200 Message-Id: <20221010070330.725277419@linuxfoundation.org> X-Mailer: git-send-email 2.38.0 In-Reply-To: <20221010070330.159911806@linuxfoundation.org> References: <20221010070330.159911806@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Tetsuo Handa commit deee93d13d385103205879a8a0915036ecd83261 upstream. syzbot is reporting attempt to schedule hdev->cmd_work work from system_wq WQ into hdev->workqueue WQ which is under draining operation [1], for commit c8efcc2589464ac7 ("workqueue: allow chained queueing during destruction") does not allow such operation. The check introduced by commit 877afadad2dce8aa ("Bluetooth: When HCI work queue is drained, only queue chained work") was incomplete. Use hdev->workqueue WQ when queuing hdev->{cmd,ncmd}_timer works because hci_{cmd,ncmd}_timeout() calls queue_work(hdev->workqueue). Also, protect the queuing operation with RCU read lock in order to avoid calling queue_delayed_work() after cancel_delayed_work() completed. Link: https://syzkaller.appspot.com/bug?extid=3D243b7d89777f90f7613b [1] Reported-by: syzbot Signed-off-by: Tetsuo Handa Fixes: 877afadad2dce8aa ("Bluetooth: When HCI work queue is drained, only q= ueue chained work") Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_core.c | 15 +++++++++++++-- net/bluetooth/hci_event.c | 6 ++++-- 2 files changed, 17 insertions(+), 4 deletions(-) --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -597,6 +597,15 @@ static int hci_dev_do_reset(struct hci_d =20 /* Cancel these to avoid queueing non-chained pending work */ hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE); + /* Wait for + * + * if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE)) + * queue_delayed_work(&hdev->{cmd,ncmd}_timer) + * + * inside RCU section to see the flag or complete scheduling. + */ + synchronize_rcu(); + /* Explicitly cancel works in case scheduled after setting the flag. */ cancel_delayed_work(&hdev->cmd_timer); cancel_delayed_work(&hdev->ncmd_timer); =20 @@ -4056,12 +4065,14 @@ static void hci_cmd_work(struct work_str if (res < 0) __hci_cmd_sync_cancel(hdev, -res); =20 + rcu_read_lock(); if (test_bit(HCI_RESET, &hdev->flags) || hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE)) cancel_delayed_work(&hdev->cmd_timer); else - schedule_delayed_work(&hdev->cmd_timer, - HCI_CMD_TIMEOUT); + queue_delayed_work(hdev->workqueue, &hdev->cmd_timer, + HCI_CMD_TIMEOUT); + rcu_read_unlock(); } else { skb_queue_head(&hdev->cmd_q, skb); queue_work(hdev->workqueue, &hdev->cmd_work); --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3766,16 +3766,18 @@ static inline void handle_cmd_cnt_and_ti { cancel_delayed_work(&hdev->cmd_timer); =20 + rcu_read_lock(); if (!test_bit(HCI_RESET, &hdev->flags)) { if (ncmd) { cancel_delayed_work(&hdev->ncmd_timer); atomic_set(&hdev->cmd_cnt, 1); } else { if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE)) - schedule_delayed_work(&hdev->ncmd_timer, - HCI_NCMD_TIMEOUT); + queue_delayed_work(hdev->workqueue, &hdev->ncmd_timer, + HCI_NCMD_TIMEOUT); } } + rcu_read_unlock(); } =20 static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data,