Received: by 2002:a05:6359:c8b:b0:c7:702f:21d4 with SMTP id go11csp2950371rwb; Mon, 3 Oct 2022 07:43:41 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4UKbohcie2c4QcEasr8JxzR64gzZtiMlOSvo0pn1t1mchzzt/v2qLLavrBosWYwZEFUQKt X-Received: by 2002:a17:906:5d11:b0:787:807e:5b8a with SMTP id g17-20020a1709065d1100b00787807e5b8amr15267478ejt.559.1664808220938; Mon, 03 Oct 2022 07:43:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1664808220; cv=none; d=google.com; s=arc-20160816; b=WSQJevkyzCeAxmGDhynBAOp04cUpIjue2wOKeT5A1hmoP0U3eJo0jRPiFCBGzx7ps1 ldDM8rLeZGDTtzH0CUHXwpqtUoxZa06RUIO6C+xGPR/HCh7jUe6fg7gXDiiwyNO4Yg3M cKxVcEmAGxcAmkMvyeSRIwWYNmpjWlD2Z1sdIhoQszcmz7LEnVcIBxgFVKM04gu6vZ5V 1P3CJXZKRVkhO/glhLiV+V2KvKORhJ5V9aeR2vnfy5J22AgJ70T2BtoZzNygS6f0XJc9 BZZMC3acmHmjN/DHug5LNyXo3BXXT8MqvJR9kA+wRoO6kwPU/ALmwhlQJcpEwHZym5EE UU1A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:to:from; bh=G8tIKLjcAYcH3ED2RByBi+jgb/RVOCEmWxyJEW8mCqI=; b=amgUv0btOKn2BglpzmbVbFi3FdkFKRzk3X8N1JsCAQaTTPrQWgm+x+A6NFCpC0geCv XV9vJEpah39+p4mN1zMQUAz7tGdL450EfMOGBPrkz0GWc0JKmJSQWP0XiLSgcnE/1mws gguIbA142v4s+gfLkD9y9nSJrxFXCO7G88bYK5WgtIBniZzhLkpxJPIR56qQkPNT5Wfm copPw8wqn8lhwlvCD3B3/gzzke139BCBX4+QiM4n1pC//wRDWbL4/7jkRjQdIW/kjvcP ASK4aal1wY2YeTAD5CE40u0zsh6w1x6fMkYc2KaazCz0+zHgYjF67Q3U/xeWkPYWO3pb idiw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id sh11-20020a1709076e8b00b0074172ed562dsi8465043ejc.813.2022.10.03.07.42.48; Mon, 03 Oct 2022 07:43:40 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229996AbiJCOdn (ORCPT + 99 others); Mon, 3 Oct 2022 10:33:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230001AbiJCOdl (ORCPT ); Mon, 3 Oct 2022 10:33:41 -0400 Received: from mout.kundenserver.de (mout.kundenserver.de [217.72.192.73]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C964481D6 for ; Mon, 3 Oct 2022 07:33:39 -0700 (PDT) Received: from evilbit.green-communications.fr ([92.154.77.116]) by mrelayeu.kundenserver.de (mreue109 [213.165.67.119]) with ESMTPSA (Nemesis) id 1MHoZM-1oSfDC2YJa-00EvIn; Mon, 03 Oct 2022 16:33:36 +0200 From: Nicolas Cavallari To: Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , linux-bluetooth@vger.kernel.org Subject: [RFC PATCH] Bluetooth: Add a workaround for SCO over USB HCI design defect Date: Mon, 3 Oct 2022 16:25:58 +0200 Message-Id: <20221003142558.17914-1-nicolas.cavallari@green-communications.fr> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Provags-ID: V03:K1:SwjEmG3MMXAwmEZ4DK7NTvF88aIq/pRfwfvzr9ET54E3kHzcSrd r7Hd9jCa2n3hIsPVFzNBqoy38MR+69+fGw+ornDaZ6Mj5tQhYyTRTB1MCcvcfUbrlVT/4o+ BcwkwtISoz2+Ks5h/NWjIZEViNnczGzxylZAY49ddqhZVJEf9r1DsX05Eqcy1SmOoNOIxcc UvswZfP8qQhcXv3/yuxAw== X-UI-Out-Filterresults: notjunk:1;V03:K0:g5AHpQHCaOs=:LW/7rVZ9Hwp0ngyguf/TRR gSp1+bgOZt212rGHgTSMtT4aRqPwL1931YIRzJKgAA21TGZi/ZAN69m60kDq1AnpGqCYluW4t 3vUEVIsYQJlXogQJQ8QFnlklo0nnL7iwtFMv4+bSShQVbIc2hHV99upqokxI/K1sg2IaIc/No NLOPSvzOuduhBTcOwZ1bwF08h1CBXM61Is+EKT8eI2iosP14Us+phR6rvHAWh4lnchG9XjeFZ wJK6aSzYrAwx+0R+L01YNbJla7fLFzK5hnzgVKaTeMQcVWVRYglMvAfhnDCEzTaBjyygSSE84 npnlbzeB5LTVvjQU9C6u9KqIMQ+Oz5W7zsv7vLzLA2gw0dZEG2JfIoBEkZR6/Mq1LyGJ7Yv1T Cmybbb+R3aOLW2hpwvhLa/Blk7+WqWfWOjKZTJrdQHZkwt1d/aYe/bR/kaVyar8MDlYlwhMLw 98YCwNaFsyz87WUkmwteNUmZRikDQVunEpxGb/mEkI+h9NRU25QQLbIFl40l8MhWRQ6HMa7lA drJDPAoy/aACAI5FL9T1KUR1LNiOXhfYsoh3JflZ2oP4mLKeN8eNBEq82BLR9KTDEvx1bAezF vFVKjr5PF5Yr8oLxKhW087x4vXt0z//DyaCUecO5YnmnnWSSYYzc1ID+KPXraOa0ly+GVQO0Z OIoosbzqnmulnTVv3rjlnr4TWGMNwpWJ9WuPhoWYdDoGjg7ezSre2eymiPCdm1jnl23RnWw3h 6bM62mIIAWlm/+QtKlHVcwHiVw1+GYDla9xS0ORiBdfVhdeu/zZ9ZgvG5mu/sIJ9qdoBsH0m9 Ru0JwXkALMAuPZikNtnz0ut/vLcokXnu8vOdVvx+iLZ97bil2I= X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=ham 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 The USB interface between the host and the bluetooth adapter used for SCO packets uses an USB isochronous endpoint with a fragmentation scheme that does not tolerate errors. Except USB isochronous transfers do not provide a reliable stream with guaranteed delivery (There is no retry on error, see USB spec v2.0 5.6 and 8.5.5). To fragment a packet, the bluetooth HCI simply split it in parts and transfer them as-is. The receiver is expected to reconstruct the packet by assuming the first fragment contains the header and parsing its size field. There is no error detection either. If a fragment is lost, the end result is that the kernel is no longer synchronized and will pass malformed data to the upper layers, since it has no way to tell if the first fragment is an actual first fragment or a continuation fragment. Resynchronization can only happen by luck and requires an unbounded amount of time. The typical symptom for a HSP/HFP bluetooth headset is that the microphone stops working and dmesg contains piles of rate-limited "Bluetooth: hci0: SCO packet for unknown connection handle XXXX" errors for an undeterminate amount of time, until the kernel accidently resynchronize. A workaround is to ask the upper layer to prevalidate the first fragment header. This is not possible with user channels so this workaround is disabled in this case. Signed-off-by: Nicolas Cavallari --- drivers/bluetooth/btusb.c | 7 +++++-- include/net/bluetooth/hci_core.h | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 15caa6469538..f6256af98233 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -980,9 +980,12 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) if (skb->len == HCI_SCO_HDR_SIZE) { /* Complete SCO header */ - hci_skb_expect(skb) = hci_sco_hdr(skb)->dlen; + struct hci_sco_hdr *hdr = hci_sco_hdr(skb); - if (skb_tailroom(skb) < hci_skb_expect(skb)) { + hci_skb_expect(skb) = hdr->dlen; + + if (skb_tailroom(skb) < hci_skb_expect(skb) || + !hci_conn_prevalidate_sco_hdr(data->hdev, hdr)) { kfree_skb(skb); skb = NULL; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e7862903187d..d589b54e89e6 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1286,6 +1286,26 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev) return NULL; } +static inline bool hci_conn_prevalidate_sco_hdr(struct hci_dev *hdev, + struct hci_sco_hdr *hdr) +{ + __u16 handle; + + if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) + // Can't validate, userspace controls everything. + return true; + + handle = hci_handle(__le16_to_cpu(hdr->handle)); + + switch (hci_conn_lookup_type(hdev, handle)) { + case SCO_LINK: + case ESCO_LINK: + return true; + default: + return false; + } +} + int hci_disconnect(struct hci_conn *conn, __u8 reason); bool hci_setup_sync(struct hci_conn *conn, __u16 handle); void hci_sco_setup(struct hci_conn *conn, __u8 status); -- 2.37.2