From patchwork Wed Nov 16 20:00:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Szymon Heidrich X-Patchwork-Id: 1704865 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=YVUsPTV4; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NCKgd2JP5z23lt for ; Thu, 17 Nov 2022 10:55:57 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3BA1C851F1; Thu, 17 Nov 2022 00:53:56 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YVUsPTV4"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id EAA74851C7; Wed, 16 Nov 2022 21:01:01 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [IPv6:2a00:1450:4864:20::22a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 41A3B806EE for ; Wed, 16 Nov 2022 21:00:59 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=szymon.heidrich@gmail.com Received: by mail-lj1-x22a.google.com with SMTP id d3so23281351ljl.1 for ; Wed, 16 Nov 2022 12:00:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-language:to:subject:from:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=Gfoqr733ePbMzRea36C4jUqV75/nkFuXmYnBhRasT8Q=; b=YVUsPTV4p67CUHuM1TAwvrWIke7biuckBpMAb7ppzHU1HAFn0noYgJNaEq3uJMh9cq VhBUnIBa4Q+yj34L/+DFVsBcz6yVl0NPUlLsWDMNlC4WemzL97/PsBMCpjAJlguN5uHt LmH2S/zku/kB9iPovLXVmFmuMwGNAJd1aEe+HCMynetUv4gTLKZxMQnTh0MiF8oAhZO1 NYMKZ90Zwzwdzcy/os7tPbKLB6aLD/XYvA0jYRsaOK0GN6No785rsxp7bwoeqFjn8aoi hIJOfQbrbJuzb0UYa/iZj1cbcz8/FHSujhCsSyN9ISG0+tgg/PNSrkq3azWFySdbQzPN 9Z9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-language:to:subject:from:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Gfoqr733ePbMzRea36C4jUqV75/nkFuXmYnBhRasT8Q=; b=Yr6d6TSggyAqHdq+k4Ey21FSOxrIMyErMBBXOCWYEFTMUnDiDrkuMkOvS9d8lYfyvY yUV5n3oSECVcw8tPzapSv1hZ1RfMGQg4cSPlTS3iO32fPxwnwxUJ6SYkTEyVf9jSgN6J h/IuKOZS/AxlBLesibDZ33jeNM8v4kOwAulxziRbfHcOPU6UAoA97g2MuTm6f9dUUNlJ pfXcAUXfiORfWKK4JtGyf4HbgDB5+CklaulFuB8SchgVPcDREXIWpnZw0Sk9c/VNQlKJ sRejg4Rq82L9tbC4PqlaU0n6Sj3Q1rQKGoI95SIZV4CwDIIitkpiZsWY+RTLMU7x4pYc nVhg== X-Gm-Message-State: ANoB5pm41VjtBTtXLkXSuk9qdFo6b45+GH8ACrX3d0C8oQLFNEqCFLDl sDug7qcFoGdB6xeI+WxtPf5fY3m2ickinQJo X-Google-Smtp-Source: AA0mqf7Y9i+iJd8IM3mA2vJEcAuzrM2V3vsV0EMmKz94br7Olcsp43bOTlwWQx/FgWyQFjBhiUaZ/g== X-Received: by 2002:a05:651c:1a26:b0:277:309:f1ad with SMTP id by38-20020a05651c1a2600b002770309f1admr8331579ljb.244.1668628858163; Wed, 16 Nov 2022 12:00:58 -0800 (PST) Received: from [192.168.50.20] (077222237105.warszawa.vectranet.pl. [77.222.237.105]) by smtp.gmail.com with ESMTPSA id u12-20020ac258cc000000b0049f87fb416dsm2763078lfo.12.2022.11.16.12.00.57 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 16 Nov 2022 12:00:57 -0800 (PST) Message-ID: <4bf3de35-6976-2380-df2f-41ab5c0c5f3b@gmail.com> Date: Wed, 16 Nov 2022 21:00:56 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.4.2 From: Szymon Heidrich Subject: USB Device buffer overflow To: u-boot@lists.denx.de Content-Language: en-US X-Mailman-Approved-At: Thu, 17 Nov 2022 00:53:55 +0100 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean Hello, Similar to CVE-2021-39685 affecting the Linux kernel U-Boot is vulnerable to a buffer overflow present in the USB Gadget stack. Handling of a control transfer request with wLength larger than USB_BUFSIZ (4096) may result in a buffer overflow. The buffer for USB control endpoint is allocated in the composite_bind function implemented in drivers/usb/gadget/composite.c. The buffer size is set to USB_BUFSIZ (4096) bytes. > /* preallocate control response and buffer */ > cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); > if (!cdev->req) > goto fail; > cdev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, USB_BUFSIZ); > if (!cdev->req->buf) > goto fail; > cdev->req->complete = composite_setup_complete; > gadget->ep0->driver_data = cdev; In the composite_setup function data transfer phase is set up to the length of "value" bytes which in multiple cases may be controlled by an attacker (is set to wLength). > if (value >= 0) { > req->length = value; > req->zero = value < w_length; > value = usb_ep_queue(gadget->ep0, req, GFP_KERNEL); > if (value < 0) { > debug("ep_queue --> %d\n", value); > req->status = 0; > composite_setup_complete(gadget->ep0, req); > } > } In example the OS descriptor handler may be forced to set value to w_length. > } else { > /* "extended compatibility ID"s */ > count = count_ext_compat(os_desc_cfg); > buf[8] = count; > count *= 24; /* 24 B/ext compat desc */ > count += 16; /* header */ > put_unaligned_le32(count, buf); > buf += 16; > fill_ext_compat(os_desc_cfg, buf); > value = w_length; > } Execution of this code path for wLength set to a value larger then USB_BUFSIZ will result in a buffer overflow. Since wLength is a double byte value it may have values up to 0xffff. Besides the common OS descriptor handler this issue may be exploited for some of the available gadgets e.g. f_dfu, f_sdp where "value" is derived from wLength. drivers/usb/gadget/f_dfu.c > static int handle_dnload(struct usb_gadget *gadget, u16 len) > { > struct usb_composite_dev *cdev = get_gadget_data(gadget); > struct usb_request *req = cdev->req; > struct f_dfu *f_dfu = req->context; > > if (len == 0) > f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC; > > req->complete = dnload_request_complete; > > return len; > } drivers/usb/gadget/f_sdp.c > if (req_type == USB_TYPE_CLASS) { > int report = w_value & HID_REPORT_ID_MASK; > > /* HID (SDP) request */ > switch (ctrl->bRequest) { > case HID_REQ_SET_REPORT: > switch (report) { > case 1: > value = SDP_COMMAND_LEN + 1; > req->complete = sdp_rx_command_complete; > sdp_func->ep_int_enable = false; > break; > case 2: > value = len; > req->complete = sdp_rx_data_complete; > sdp_func->state = SDP_STATE_RX_FILE_DATA_BUSY; > break; > } > } > } Please find attached a patch addressing this issue. Depending on request direction wLength larger than USB_BUFSIZ will result in either endpoint stall or value trim. Best regards, Szymon From 1723d976ab0387be0d91b177011559cb07a66e03 Mon Sep 17 00:00:00 2001 From: Szymon Heidrich Date: Wed, 9 Nov 2022 17:55:34 +0100 Subject: [PATCH] Prevent buffer overflow on USB control endpoint Assure that the control endpoint buffer of size USB_BUFSIZ (4096) can not be overflown during handling of USB control transfer requests with wLength greater than USB_BUFSIZ. Signed-off-by: Szymon Heidrich --- drivers/usb/gadget/composite.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2a309e62..cb89f6dc 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1019,6 +1019,17 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) u8 endp; struct usb_configuration *c; + if (w_length > USB_BUFSIZ) { + if (ctrl->bRequestType & USB_DIR_IN) { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + *temp = cpu_to_le16(USB_BUFSIZ); + w_length = USB_BUFSIZ; + } else { + goto done; + } + } + /* * partial re-init of the response message; the function or the * gadget might need to intercept e.g. a control-OUT completion