Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp710525iog; Wed, 29 Jun 2022 08:40:39 -0700 (PDT) X-Google-Smtp-Source: AGRyM1t9hG1cX7peYLskYtCQ391Qym0P7iFBjUYJwFTtmhaoeFK4SOHmHhLVhv4kyqNRn93q9W8Z X-Received: by 2002:a05:6402:510e:b0:435:9052:3b16 with SMTP id m14-20020a056402510e00b0043590523b16mr5354837edd.20.1656517239382; Wed, 29 Jun 2022 08:40:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1656517239; cv=none; d=google.com; s=arc-20160816; b=xGH5yP1Ow2aNr4IY14uUYycFyvutf34vxa9Xy86U1YIZfqExizqr4PZBE8loht3hrm 5Ty97dOwlsE8AHxGbKidqupyR3tM/P9/KKNRG65Xx9khp7iyI3u7Rj8VMiZ3FKkblD2T zQ6e19UY8udCNTl6rvqzLzrziKe2/Y46+Sep3Fx6bNsWnhjK0srTUT+cyoWz10QQG11W QYj/2PEjhfUswpOefevYq2U4nRVfnoM3T4horGZ745Z2OLxmCYX+Tfd+JDBDx1fYpVXK g8PfZ3khVMdVk9qFJNQtUYz5jhFVMxgCBuKoZaAzTT6+HmDjgti/KOydUz7rSiVQuACI 0yLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature; bh=cK/6BR9syE4gm1OltzJi9wBv5dsQLsnv5HxX5cDra8U=; b=ZCl9ke7Whj5JSr+JeC766NIobBaW2KZavHsM05qbP8ewXdass0A/AezIpyDpGUpHxm fiWy3NmTONDEf1n4QV58LmArevxqQDAzkfQ3RgswZEyu9UBEfjWCSAqRUUCWUPprARMA 2MjsXzAU5LYcSFeYlfaeEgLR9EYl9S4JzP4q/akKaMIYeqyF+UMtM3xoabaljVa4s8Eq ZGzzma14kjsBULmQtUHiaNo2VyjO1WwDLWPODJar1zBd30LA2BPrKJZm1kZPpp7f0hgk LBzYVSNPcN9MQNS29QDOJ9mtBIqVS6Lu61yThQReVNZz7qq/O9TBiCuyVo1iAVAcz8cH jhYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=F+vIL28b; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id eb13-20020a0564020d0d00b0043587e6b472si2880842edb.132.2022.06.29.08.39.40; Wed, 29 Jun 2022 08:40:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=F+vIL28b; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234134AbiF2P2K (ORCPT + 99 others); Wed, 29 Jun 2022 11:28:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232194AbiF2P2H (ORCPT ); Wed, 29 Jun 2022 11:28:07 -0400 Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5794831913 for ; Wed, 29 Jun 2022 08:28:04 -0700 (PDT) Received: by mail-wm1-x32b.google.com with SMTP id u12-20020a05600c210c00b003a02b16d2b8so9832242wml.2 for ; Wed, 29 Jun 2022 08:28:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=cK/6BR9syE4gm1OltzJi9wBv5dsQLsnv5HxX5cDra8U=; b=F+vIL28bRGa7aD8qx2tmDbcPHZrLWIfXbgPGGzJKguLsdwOcJPiJNuOZVFR1p3GNmv RuI+kJnnhKwC+t8wyz6aSVvVMrwst0zu8TGS+w2Eqc8ZOWSY1UCZJ0yVimLY5v2x+mF4 7ktYjnvpfOT3P0cpQeGg2vqwGxyym2QX2hMtqDcFSFZl3xm04OkTd/6tUx8+XmJq6Koa 5SNhGxAmwZudfg0sVOh9NYpw18wOD40uWXRpuVCTq05tQpV4N5/ZIdMEIUoNtZo4z/wK QA9r6N081v5PdV0+i6PLovT2+47kuDi48Ssj2mwUh/8BfCbF1nW65s0GitMLHKPtRMjB zqAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=cK/6BR9syE4gm1OltzJi9wBv5dsQLsnv5HxX5cDra8U=; b=MqJFnifGflokwFbDFc/yENG8swVtz5HyZ2eUj4f3vRK+QxInSakziWRFkrP98xGiuM P3ttIJXI46eS5lOj+bK44EI3jyf4pOWsIGXd1vqt9gf3YjIPea1xkMqhkUd2Hln224zG wy3+eQ2+uHIkhUzt2MrcNaMgitxBMzMHNVCg/mAFFH05XuvzNGeqXRZsvBvXbvuTLR5X 8Qa/+Cm7DoeyEqMTRE23/5iVgm3RfWsC4mnA12LKMbT1mZ4UjVwkhV3v3rIvxag5jo4C pVDwkFfGmcI6SIE/wqUc1kBmcPyaSLbyGVdTF+CGZH/O7+j3qWWMx9b5E5l0GrHuYbiY vY/g== X-Gm-Message-State: AJIora98dd6WfQtGHrQGt1wBxKwMZ2fnqP2gHCIj10ssOfrcmdwBD7w5 AzKC/LNV0SOP76quOEJT4qvbWw== X-Received: by 2002:a05:600c:4149:b0:3a0:4728:60e7 with SMTP id h9-20020a05600c414900b003a0472860e7mr4332881wmm.10.1656516482749; Wed, 29 Jun 2022 08:28:02 -0700 (PDT) Received: from google.com (cpc155339-bagu17-2-0-cust87.1-3.cable.virginm.net. [86.27.177.88]) by smtp.gmail.com with ESMTPSA id o5-20020a056000010500b00210352bf36fsm16300688wrx.33.2022.06.29.08.28.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jun 2022 08:28:02 -0700 (PDT) Date: Wed, 29 Jun 2022 16:28:00 +0100 From: Lee Jones To: Luiz Augusto von Dentz Cc: Eric Dumazet , LKML , stable@kernel.org, Marcel Holtmann , Johan Hedberg , "David S. Miller" , Jakub Kicinski , Paolo Abeni , "linux-bluetooth@vger.kernel.org" , netdev Subject: Re: [RESEND 1/1] Bluetooth: Use chan_list_lock to protect the whole put/destroy invokation Message-ID: References: <20220622082716.478486-1-lee.jones@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org On Tue, 28 Jun 2022, Luiz Augusto von Dentz wrote: > Hi Eric, Lee, > > On Mon, Jun 27, 2022 at 4:39 PM Luiz Augusto von Dentz > wrote: > > > > Hi Eric, Lee, > > > > On Mon, Jun 27, 2022 at 7:41 AM Eric Dumazet wrote: > > > > > > On Wed, Jun 22, 2022 at 10:27 AM Lee Jones wrote: > > > > > > > > This change prevents a use-after-free caused by one of the worker > > > > threads starting up (see below) *after* the final channel reference > > > > has been put() during sock_close() but *before* the references to the > > > > channel have been destroyed. > > > > > > > > refcount_t: increment on 0; use-after-free. > > > > BUG: KASAN: use-after-free in refcount_dec_and_test+0x20/0xd0 > > > > Read of size 4 at addr ffffffc114f5bf18 by task kworker/u17:14/705 > > > > > > > > CPU: 4 PID: 705 Comm: kworker/u17:14 Tainted: G S W 4.14.234-00003-g1fb6d0bd49a4-dirty #28 > > > > Hardware name: Qualcomm Technologies, Inc. SM8150 V2 PM8150 Google Inc. MSM sm8150 Flame DVT (DT) > > > > Workqueue: hci0 hci_rx_work > > > > Call trace: > > > > dump_backtrace+0x0/0x378 > > > > show_stack+0x20/0x2c > > > > dump_stack+0x124/0x148 > > > > print_address_description+0x80/0x2e8 > > > > __kasan_report+0x168/0x188 > > > > kasan_report+0x10/0x18 > > > > __asan_load4+0x84/0x8c > > > > refcount_dec_and_test+0x20/0xd0 > > > > l2cap_chan_put+0x48/0x12c > > > > l2cap_recv_frame+0x4770/0x6550 > > > > l2cap_recv_acldata+0x44c/0x7a4 > > > > hci_acldata_packet+0x100/0x188 > > > > hci_rx_work+0x178/0x23c > > > > process_one_work+0x35c/0x95c > > > > worker_thread+0x4cc/0x960 > > > > kthread+0x1a8/0x1c4 > > > > ret_from_fork+0x10/0x18 > > > > > > > > Cc: stable@kernel.org > > > > > > When was the bug added ? (Fixes: tag please) > > > > > > > Cc: Marcel Holtmann > > > > Cc: Johan Hedberg > > > > Cc: Luiz Augusto von Dentz > > > > Cc: "David S. Miller" > > > > Cc: Eric Dumazet > > > > Cc: Jakub Kicinski > > > > Cc: Paolo Abeni > > > > Cc: linux-bluetooth@vger.kernel.org > > > > Cc: netdev@vger.kernel.org > > > > Signed-off-by: Lee Jones > > > > --- > > > > net/bluetooth/l2cap_core.c | 4 ++-- > > > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > > > > > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c > > > > index ae78490ecd3d4..82279c5919fd8 100644 > > > > --- a/net/bluetooth/l2cap_core.c > > > > +++ b/net/bluetooth/l2cap_core.c > > > > @@ -483,9 +483,7 @@ static void l2cap_chan_destroy(struct kref *kref) > > > > > > > > BT_DBG("chan %p", chan); > > > > > > > > - write_lock(&chan_list_lock); > > > > list_del(&chan->global_l); > > > > - write_unlock(&chan_list_lock); > > > > > > > > kfree(chan); > > > > } > > > > @@ -501,7 +499,9 @@ void l2cap_chan_put(struct l2cap_chan *c) > > > > { > > > > BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref)); > > > > > > > > + write_lock(&chan_list_lock); > > > > kref_put(&c->kref, l2cap_chan_destroy); > > > > + write_unlock(&chan_list_lock); > > > > } > > > > EXPORT_SYMBOL_GPL(l2cap_chan_put); > > > > > > > > > > > > > > I do not think this patch is correct. > > > > > > a kref does not need to be protected by a write lock. > > > > > > This might shuffle things enough to work around a particular repro you have. > > > > > > If the patch was correct why not protect kref_get() sides ? > > > > > > Before the &hdev->rx_work is scheduled (queue_work(hdev->workqueue, > > > &hdev->rx_work), > > > a reference must be taken. > > > > > > Then this reference must be released at the end of hci_rx_work() or > > > when hdev->workqueue > > > is canceled. > > > > > > This refcount is not needed _if_ the workqueue is properly canceled at > > > device dismantle, > > > in a synchronous way. > > > > > > I do not see this hdev->rx_work being canceled, maybe this is the real issue. > > > > > > There is a call to drain_workqueue() but this is not enough I think, > > > because hci_recv_frame() > > > can re-arm > > > queue_work(hdev->workqueue, &hdev->rx_work); > > > > I suspect this likely a refcount problem, we do l2cap_get_chan_by_scid: > > > > /* Find channel with given SCID. > > * Returns locked channel. */ > > static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn > > *conn, u16 cid) > > > > So we return a locked channel but that doesn't prevent another thread > > to call l2cap_chan_put which doesn't care about l2cap_chan_lock so > > perhaps we actually need to host a reference while we have the lock, > > at least we do something like that on l2cap_sock.c: > > > > l2cap_chan_hold(chan); > > l2cap_chan_lock(chan); > > > > __clear_chan_timer(chan); > > l2cap_chan_close(chan, ECONNRESET); > > l2cap_sock_kill(sk); > > > > l2cap_chan_unlock(chan); > > l2cap_chan_put(chan); > > Perhaps something like this: I'm struggling to apply this for test: "error: corrupt patch at line 6" Please could you attach a `git format-patch`ed patch instead? > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c > index 09ecaf556de5..9050b6af3577 100644 > --- a/net/bluetooth/l2cap_core.c > +++ b/net/bluetooth/l2cap_core.c > @@ -111,7 +111,7 @@ static struct l2cap_chan > *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, > } > > /* Find channel with given SCID. > - * Returns locked channel. */ > + * Returns a reference locked channel. */ > static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, > u16 cid) > { > @@ -119,15 +119,17 @@ static struct l2cap_chan > *l2cap_get_chan_by_scid(struct l2cap_conn *conn, > > mutex_lock(&conn->chan_lock); > c = __l2cap_get_chan_by_scid(conn, cid); > - if (c) > + if (c) { > + l2cap_chan_hold(c); > l2cap_chan_lock(c); > + } > mutex_unlock(&conn->chan_lock); > > return c; > } > > /* Find channel with given DCID. > - * Returns locked channel. > + * Returns a reference locked channel. > */ > static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, > u16 cid) > @@ -136,8 +138,10 @@ static struct l2cap_chan > *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, > > mutex_lock(&conn->chan_lock); > c = __l2cap_get_chan_by_dcid(conn, cid); > - if (c) > + if (c) { > + l2cap_chan_hold(c); > l2cap_chan_lock(c); > + } > mutex_unlock(&conn->chan_lock); > > return c; > @@ -4464,6 +4468,7 @@ static inline int l2cap_config_req(struct > l2cap_conn *conn, > > unlock: > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > return err; > } > > @@ -4578,6 +4583,7 @@ static inline int l2cap_config_rsp(struct > l2cap_conn *conn, > > done: > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > return err; > } > > @@ -5305,6 +5311,7 @@ static inline int l2cap_move_channel_req(struct > l2cap_conn *conn, > l2cap_send_move_chan_rsp(chan, result); > > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > > return 0; > } > @@ -5397,6 +5404,7 @@ static void l2cap_move_continue(struct > l2cap_conn *conn, u16 icid, u16 result) > } > > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > } > > static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid, > @@ -5489,6 +5497,7 @@ static int l2cap_move_channel_confirm(struct > l2cap_conn *conn, > l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid); > > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > > return 0; > } > @@ -5524,6 +5533,7 @@ static inline int > l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, > } > > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > > return 0; > } > @@ -5896,12 +5906,11 @@ static inline int l2cap_le_credits(struct > l2cap_conn *conn, > if (credits > max_credits) { > BT_ERR("LE credits overflow"); > l2cap_send_disconn_req(chan, ECONNRESET); > - l2cap_chan_unlock(chan); > > /* Return 0 so that we don't trigger an unnecessary > * command reject packet. > */ > - return 0; > + goto unlock; > } > > chan->tx_credits += credits; > @@ -5912,7 +5921,9 @@ static inline int l2cap_le_credits(struct > l2cap_conn *conn, > if (chan->tx_credits) > chan->ops->resume(chan); > > +unlock: > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > > return 0; > } > @@ -7598,6 +7609,7 @@ static void l2cap_data_channel(struct l2cap_conn > *conn, u16 cid, > > done: > l2cap_chan_unlock(chan); > + l2cap_chan_put(chan); > } > > static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, > > > > > > > -- Lee Jones [李琼斯] Principal Technical Lead - Developer Services Linaro.org │ Open source software for Arm SoCs Follow Linaro: Facebook | Twitter | Blog