Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp626074pxf; Wed, 24 Mar 2021 11:52:31 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwjv1frVAVEDwcvuhI65EHuwr/OAqZp4BsokaDG0Jf/REMdwDe+i/EUC782dczRuVe8wRuz X-Received: by 2002:a17:906:78d:: with SMTP id l13mr5411023ejc.97.1616611950889; Wed, 24 Mar 2021 11:52:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616611950; cv=none; d=google.com; s=arc-20160816; b=hGG2k5i/piql/CVf/nlXDFTyaMP7SS7sP9S9Z7Q/4NI9EKGa2+SL60cLCnwc1I3L9P WOnrK9EBx3cXAYfx0XK/83MEk/rap0BFwMdiPBCv4BJRCKS0ZgstxI9r3YdJMdnYtvPM Av5tQg7bwWl8TH763Hf/aUAFFxcB4UimTjHetyqrDNg13UMdrmI8pHfV97IP6rPRvo8f 8yhcQHOY+T5DLgeFLMgN8Lmo7IeZ/KiPtfExKaXizcwX9cmQX1UDrmLySt8aS2pZ+9YH tiUMcmI80kverG2SKmscC7VfAHAeXCrbRYdfX3sw1QT02arGp0COT2Dp/Jpl1BoEIUuF 4pXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:mime-version:message-id:date :dkim-signature; bh=rKcNbR+LxTP4j4KG6QhvAtJ90pK5ENJOnzBCgg91Onk=; b=bqsAQ4P6+s6qc86I4h0Qu0O6bZ71bufJyA+J1pMgNqurvBqTCtTxAT9i+AUsz5EuGY ++/r2Rgy0Lf9NM1eDE9mpV/I7iZbCxTh9vFU8IyqXc2eCvwaIgeHHBx2CDYgxG7P2yb1 ar4E+N4ORsbdMMJP+efFoB7rPDENqVdmVdDcmIlaT7eNXTkYyhSqwGaIjsADagZea2aw QkCzihy1hVOy+zEvLtK3zo1Uky6MYWwRg4mDyUHcN69nmM8F6BZWTwCj5Ig4EWXb/Z9c t1MqkGoDs7J1sDeTeErSMFaH4m6n/3iKQyT3gfBzxFucpneogTZFHoFf4WqNzJcTNPxn iX4g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=tHmA+b14; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bx3si2358455edb.594.2021.03.24.11.51.49; Wed, 24 Mar 2021 11:52:30 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=tHmA+b14; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237604AbhCXSrf (ORCPT + 99 others); Wed, 24 Mar 2021 14:47:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49740 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237587AbhCXSrJ (ORCPT ); Wed, 24 Mar 2021 14:47:09 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C451C061763 for ; Wed, 24 Mar 2021 11:47:08 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id v124so3304666ybc.15 for ; Wed, 24 Mar 2021 11:47:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=rKcNbR+LxTP4j4KG6QhvAtJ90pK5ENJOnzBCgg91Onk=; b=tHmA+b14JUxfjas7gHzGU6el3u3kffAUHUkD+sPuAhvVTGZmCTtIEJYIH1lxofX4qA Fng0ME678PGbmGlVLsIfQgNeZz6r6QSH542Ex82lanWrbWfn5G9aUYLoppQDYIjlO9aD x5HrVs0t+AgFqfePObi9np1MxOJObRbzom4bWTjbV/TcSu4i0ACNCJCG9fwDq2k2cKv2 EjW1sPVQcMF/hPRN+lVWQoocH/B5UJK0T9jaeM1+ofq8yESoDPtECfhdsVW22pfdn6tc auPPqHm6ZeoP0dveluUbzuc9a5aHJrlyHpbkZiXIfGaMZ0inBit7rrZCSUJ+NawQWlry GVaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=rKcNbR+LxTP4j4KG6QhvAtJ90pK5ENJOnzBCgg91Onk=; b=GPADecUD1XkvSSLt6+iI7TX6ow1zQQaV6ijwc+VhxfnE5EqdEXuFTXarmGr+cB4XTW yH7gn4srtGZUeqvw8S9VmPpQo82ZGISI1Yl6Nd7ExVVNHch2jwQWadag+PdrJyuRn0HS e8f/d0YpuWB5/abTXtp5aXtcGm25vPswvXnIkHFtPBQPODbjwWIs0DZU4b7luDdeyANJ 7uX3hWlpZsXPP6EcOsTF7PEr3AjMQUuAp+egLK4UVBoB6SBT2oStPPCyjkdhs5JWOB/c P2mqW6G9Hb33CV+q+8Uks8gc8JIRFUDBAQju8yIYy3wpN4PO+q5l0IZDceHCQK9TrHbx PBmA== X-Gm-Message-State: AOAM531Hvaa2v8sHtUZBjvaT16oJh5OJ27U0aWWHxy+j+DV94VWACuhC ttjTNtM3bfAgyhUfNkGE+XA8m7+rYIOM15ldX+LH0eTf5oFJsvt1yP6ybD8+8Xr4nK8tpM7KZXS PlzQOaUs9ZZCJqzYYjPrSshiDhJy6goF1/MLh2wDc9oPGO4qPmMS2ZgsvJ8ORc9XFac/riRemsc 9B8ABNwF5ghfqjGUQI X-Received: from danielwinkler-linux.mtv.corp.google.com ([2620:15c:202:201:f18d:a314:46c6:7a97]) (user=danielwinkler job=sendgmr) by 2002:a25:ba10:: with SMTP id t16mr6021053ybg.222.1616611627661; Wed, 24 Mar 2021 11:47:07 -0700 (PDT) Date: Wed, 24 Mar 2021 11:47:03 -0700 Message-Id: <20210324114645.v2.1.I53e6be1f7df0be198b7e55ae9fc45c7f5760132d@changeid> Mime-Version: 1.0 X-Mailer: git-send-email 2.31.0.291.g576ba9dcdaf-goog Subject: [PATCH v2] Bluetooth: Always call advertising disable before setting params From: Daniel Winkler To: linux-bluetooth@vger.kernel.org Cc: chromeos-bluetooth-upstreaming@chromium.org, Daniel Winkler , Miao-chen Chou , "David S. Miller" , Jakub Kicinski , Johan Hedberg , Luiz Augusto von Dentz , Marcel Holtmann , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org In __hci_req_enable_advertising, the HCI_LE_ADV hdev flag is temporarily cleared to allow the random address to be set, which exposes a race condition when an advertisement is configured immediately (<10ms) after software rotation starts to refresh an advertisement. In normal operation, the HCI_LE_ADV flag is updated as follows: 1. adv_timeout_expire is called, HCI_LE_ADV gets cleared in __hci_req_enable_advertising, but hci_req configures an enable request 2. hci_req is run, enable callback re-sets HCI_LE_ADV flag However, in this race condition, the following occurs: 1. adv_timeout_expire is called, HCI_LE_ADV gets cleared in __hci_req_enable_advertising, but hci_req configures an enable request 2. add_advertising is called, which also calls __hci_req_enable_advertising. Because HCI_LE_ADV was cleared in Step 1, no "disable" command is queued. 3. hci_req for adv_timeout_expire is run, which enables advertising and re-sets HCI_LE_ADV 4. hci_req for add_advertising is run, but because no "disable" command was queued, we try to set advertising parameters while advertising is active, causing a Command Disallowed error, failing the registration. To resolve the issue, this patch removes the check for the HCI_LE_ADV flag, and always queues the "disable" request, since HCI_LE_ADV could be very temporarily out-of-sync. According to the spec, there is no harm in calling "disable" when advertising is not active. An example trace showing the HCI error in setting advertising parameters is included below, with some notes annotating the states I mentioned above: @ MGMT Command: Add Ext Adv.. (0x0055) plen 35 {0x0001} [hci0]04:05.884 Instance: 3 Advertising data length: 24 16-bit Service UUIDs (complete): 2 entries Location and Navigation (0x1819) Phone Alert Status Service (0x180e) Company: not assigned (65283) Data: 3a3b3c3d3e Service Data (UUID 0x9993): 3132333435 Scan response length: 0 @ MGMT Event: Advertising Ad.. (0x0023) plen 1 {0x0005} [hci0]04:05.885 Instance: 3 === adv_timeout_expire request starts running. This request was created before our add advertising request > HCI Event: Command Complete (0x0e) plen 4 #220 [hci0]04:05.993 LE Set Advertising Data (0x08|0x0008) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan.. (0x08|0x0009) plen 32 #221 [hci0]04:05.993 Length: 24 Service Data (UUID 0xabcd): 161718191a1b1c1d1e1f2021222324252627 > HCI Event: Command Complete (0x0e) plen 4 #222 [hci0]04:05.995 LE Set Scan Response Data (0x08|0x0009) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Adver.. (0x08|0x000a) plen 1 #223 [hci0]04:05.995 Advertising: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 4 #224 [hci0]04:05.997 LE Set Advertise Enable (0x08|0x000a) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Adve.. (0x08|0x0006) plen 15 #225 [hci0]04:05.997 Min advertising interval: 200.000 msec (0x0140) Max advertising interval: 200.000 msec (0x0140) Type: Connectable undirected - ADV_IND (0x00) Own address type: Public (0x00) Direct address type: Public (0x00) Direct address: 00:00:00:00:00:00 (OUI 00-00-00) Channel map: 37, 38, 39 (0x07) Filter policy: Allow Scan Request, Connect from Any (0x00) > HCI Event: Command Complete (0x0e) plen 4 #226 [hci0]04:05.998 LE Set Advertising Parameters (0x08|0x0006) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Adver.. (0x08|0x000a) plen 1 #227 [hci0]04:05.999 Advertising: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 #228 [hci0]04:06.000 LE Set Advertise Enable (0x08|0x000a) ncmd 1 Status: Success (0x00) === Our new add_advertising request starts running < HCI Command: Read Local N.. (0x03|0x0014) plen 0 #229 [hci0]04:06.001 > HCI Event: Command Complete (0x0e) plen 252 #230 [hci0]04:06.005 Read Local Name (0x03|0x0014) ncmd 1 Status: Success (0x00) Name: Chromebook_FB3D === Although the controller is advertising, no disable command is sent < HCI Command: LE Set Adve.. (0x08|0x0006) plen 15 #231 [hci0]04:06.005 Min advertising interval: 200.000 msec (0x0140) Max advertising interval: 200.000 msec (0x0140) Type: Connectable undirected - ADV_IND (0x00) Own address type: Public (0x00) Direct address type: Public (0x00) Direct address: 00:00:00:00:00:00 (OUI 00-00-00) Channel map: 37, 38, 39 (0x07) Filter policy: Allow Scan Request, Connect from Any (0x00) > HCI Event: Command Complete (0x0e) plen 4 #232 [hci0]04:06.005 LE Set Advertising Parameters (0x08|0x0006) ncmd 1 Status: Command Disallowed (0x0c) Reviewed-by: Miao-chen Chou Signed-off-by: Daniel Winkler --- Changes in v2: - Added btmon snippet showing HCI command failure net/bluetooth/hci_request.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 8ace5d34b01efe..2b4b99f4cedf21 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1547,8 +1547,10 @@ void __hci_req_enable_advertising(struct hci_request *req) if (!is_advertising_allowed(hdev, connectable)) return; - if (hci_dev_test_flag(hdev, HCI_LE_ADV)) - __hci_req_disable_advertising(req); + /* Request that the controller stop advertising. This can be called + * whether or not there is an active advertisement. + */ + __hci_req_disable_advertising(req); /* Clear the HCI_LE_ADV bit temporarily so that the * hci_update_random_address knows that it's safe to go ahead -- 2.31.0.291.g576ba9dcdaf-goog