From patchwork Thu Apr 25 16:05:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 10917437 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9E611575 for ; Thu, 25 Apr 2019 16:06:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9FC628BD5 for ; Thu, 25 Apr 2019 16:06:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ADD6328C04; Thu, 25 Apr 2019 16:06:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 44D4828C3F for ; Thu, 25 Apr 2019 16:06:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726896AbfDYQF7 (ORCPT ); Thu, 25 Apr 2019 12:05:59 -0400 Received: from mail-lf1-f65.google.com ([209.85.167.65]:35886 "EHLO mail-lf1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726402AbfDYQF7 (ORCPT ); Thu, 25 Apr 2019 12:05:59 -0400 Received: by mail-lf1-f65.google.com with SMTP id u17so197192lfi.3 for ; Thu, 25 Apr 2019 09:05:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jH+B5GnM61cAUeL6Upm3Ak3lJ7oLat4CM9piCjk6n50=; b=iNBSYhHPamRcbCgXc+KAxdYMMPWKF1ByH5EEw0ZM0L6hCZOcdR9+CD1/tFW3g/qisR BLXi9jAQvUHjuv2BRC9JybrBywMHlQ8YNkNcFPiY4rNtsmZ0eJcwTqzvQGvyiDb31e/M lD7TGB1Snmf+QOqvjNM5nod6TEfjS4qyL53NSY0KGvk2XU/CALnEa582OxLdRseSdigO vzQUkn75Y4GKXgBLrpwbOHYIrIMsK7qqfqseVZRZMWtEX2lgZ80aXJm90Dz1AKY69alo 2YBHNWBfRYQR1r/MNditkuiMmIdbJKMkmEsRl8pw756JPBq2Tuci2C+e9MFv+czpFoB5 E40A== X-Gm-Message-State: APjAAAWj8umivpHFGywsDAVcAlA8Zic39rLbQaGGLwd0gFnkoZcRDQu3 BSa2wQDm5ktRXYL2qKRYZLs= X-Google-Smtp-Source: APXvYqw/c1hJwjfjGJRhwG5s42NHZJMYY0m5YpteZ+is7Zw0Cl0C8wpUh1C7WUVy82Htgxs1r/y6Cw== X-Received: by 2002:ac2:4301:: with SMTP id l1mr5318832lfh.54.1556208357086; Thu, 25 Apr 2019 09:05:57 -0700 (PDT) Received: from xi.terra (c-74bee655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.190.116]) by smtp.gmail.com with ESMTPSA id w22sm4636730ljd.42.2019.04.25.09.05.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Apr 2019 09:05:55 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1hJgsl-0002ci-Iq; Thu, 25 Apr 2019 18:05:55 +0200 From: Johan Hovold To: Alan Stern , Oliver Neukum , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, Johan Hovold Subject: [PATCH 1/5] USB: serial: fix unthrottle races Date: Thu, 25 Apr 2019 18:05:36 +0200 Message-Id: <20190425160540.10036-2-johan@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190425160540.10036-1-johan@kernel.org> References: <20190425160540.10036-1-johan@kernel.org> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Fix two long-standing bugs which could potentially lead to memory corruption or leave the port throttled until it is reopened (on weakly ordered systems), respectively, when read-URB completion races with unthrottle(). First, the URB must not be marked as free before processing is complete to prevent it from being submitted by unthrottle() on another CPU. CPU 1 CPU 2 ================ ================ complete() unthrottle() process_urb(); smp_mb__before_atomic(); set_bit(i, free); if (test_and_clear_bit(i, free)) submit_urb(); Second, the URB must be marked as free before checking the throttled flag to prevent unthrottle() on another CPU from failing to observe that the URB needs to be submitted if complete() sees that the throttled flag is set. CPU 1 CPU 2 ================ ================ complete() unthrottle() set_bit(i, free); throttled = 0; smp_mb__after_atomic(); smp_mb(); if (throttled) if (test_and_clear_bit(i, free)) return; submit_urb(); Note that test_and_clear_bit() only implies barriers when the test is successful. To handle the case where the URB is still in use an explicit barrier needs to be added to unthrottle() for the second race condition. Fixes: d83b405383c9 ("USB: serial: add support for multiple read urbs") Signed-off-by: Johan Hovold --- drivers/usb/serial/generic.c | 39 +++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2274d9625f63..0fff4968ea1b 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -376,6 +376,7 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; unsigned long flags; + bool stopped = false; int status = urb->status; int i; @@ -383,33 +384,51 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) if (urb == port->read_urbs[i]) break; } - set_bit(i, &port->read_urbs_free); dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, urb->actual_length); switch (status) { case 0: + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, + data); + port->serial->type->process_read_urb(urb); break; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: dev_dbg(&port->dev, "%s - urb stopped: %d\n", __func__, status); - return; + stopped = true; + break; case -EPIPE: dev_err(&port->dev, "%s - urb stopped: %d\n", __func__, status); - return; + stopped = true; + break; default: dev_dbg(&port->dev, "%s - nonzero urb status: %d\n", __func__, status); - goto resubmit; + break; } - usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); - port->serial->type->process_read_urb(urb); + /* + * Make sure URB processing is done before marking as free to avoid + * racing with unthrottle() on another CPU. Matches the barriers + * implied by the test_and_clear_bit() in + * usb_serial_generic_submit_read_urb(). + */ + smp_mb__before_atomic(); + set_bit(i, &port->read_urbs_free); + /* + * Make sure URB is marked as free before checking the throttled flag + * to avoid racing with unthrottle() on another CPU. Matches the + * smp_mb() in unthrottle(). + */ + smp_mb__after_atomic(); + + if (stopped) + return; -resubmit: /* Throttle the device if requested by tty */ spin_lock_irqsave(&port->lock, flags); port->throttled = port->throttle_req; @@ -484,6 +503,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) port->throttled = port->throttle_req = 0; spin_unlock_irq(&port->lock); + /* + * Matches the smp_mb__after_atomic() in + * usb_serial_generic_read_bulk_callback(). + */ + smp_mb(); + if (was_throttled) usb_serial_generic_submit_read_urbs(port, GFP_KERNEL); } From patchwork Thu Apr 25 16:05:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 10917443 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 51E551575 for ; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3C0B928C04 for ; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3036328C29; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A2B2928BD5 for ; Thu, 25 Apr 2019 16:06:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726924AbfDYQGA (ORCPT ); Thu, 25 Apr 2019 12:06:00 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:35810 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726058AbfDYQGA (ORCPT ); Thu, 25 Apr 2019 12:06:00 -0400 Received: by mail-lf1-f66.google.com with SMTP id j20so201286lfh.2 for ; Thu, 25 Apr 2019 09:05:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=njCj2//bdeddp1PVnNNWH8PanEmLZ08pHEu90xXrCjg=; b=WB4OYwQd+jbumoHRpWgjHs5re78QB7FmG8Mc+3vNjadtIsTyDbPTaGLt1NkswMMdu7 PxLlOeIlnkDHWYK3q+4G8vZL4B3KIC1/rUJyWZCg0E40K568Zv4D58+SOTvg21P10EPR xdgHT1OZgqzadIDt4n2T67gFCAhAgmlQE8LPtHxdabiF5jV+pmWOFVANPp53dnsyIby9 UHXh+08MSevTzSviD2fZdseEQ4fQmCWX2k+EBGdcwWJk0etBIK92S5DtxnMI2rVYv2CD B9zdc+V2/Z4CQ/DgtI3x/nNqjGLpzPQsb2wMcbTsSwVTnVLjf6DNNzBQmgMHY+P67Mis 0lBA== X-Gm-Message-State: APjAAAXqjrIniGxfSGuhrSjy9xdxuhLLUcy+5dZ33Z66VCRzuMry7DdT qfxeNSVphACt2AmOvRUyBy4= X-Google-Smtp-Source: APXvYqyD8MPhip/tE4oFNK3U/TQBu9W/MSEOvY8jeg3OVNs9cTtxMWfuH1a3cFGpWa8ZZMt8ARkuHQ== X-Received: by 2002:a19:5507:: with SMTP id n7mr10694lfe.140.1556208357892; Thu, 25 Apr 2019 09:05:57 -0700 (PDT) Received: from xi.terra (c-74bee655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.190.116]) by smtp.gmail.com with ESMTPSA id j6sm5863103ljc.0.2019.04.25.09.05.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Apr 2019 09:05:55 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1hJgsl-0002co-M9; Thu, 25 Apr 2019 18:05:55 +0200 From: Johan Hovold To: Alan Stern , Oliver Neukum , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, Johan Hovold Subject: [PATCH 2/5] USB: serial: clean up throttle handling Date: Thu, 25 Apr 2019 18:05:37 +0200 Message-Id: <20190425160540.10036-3-johan@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190425160540.10036-1-johan@kernel.org> References: <20190425160540.10036-1-johan@kernel.org> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Clean up the throttle implementation by dropping the redundant throttle_req flag which was a remnant from back when there was only a single read URB. Also convert the throttled flag to an atomic bit flag. Signed-off-by: Johan Hovold --- drivers/usb/serial/generic.c | 34 ++++++++-------------------------- include/linux/usb/serial.h | 5 +---- 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 0fff4968ea1b..67cef3ef1e5f 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -106,12 +106,8 @@ void usb_serial_generic_deregister(void) int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port) { int result = 0; - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); - port->throttled = 0; - port->throttle_req = 0; - spin_unlock_irqrestore(&port->lock, flags); + clear_bit(USB_SERIAL_THROTTLED, &port->flags); if (port->bulk_in_size) result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL); @@ -375,7 +371,6 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; - unsigned long flags; bool stopped = false; int status = urb->status; int i; @@ -429,15 +424,10 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) if (stopped) return; - /* Throttle the device if requested by tty */ - spin_lock_irqsave(&port->lock, flags); - port->throttled = port->throttle_req; - if (!port->throttled) { - spin_unlock_irqrestore(&port->lock, flags); - usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC); - } else { - spin_unlock_irqrestore(&port->lock, flags); - } + if (test_bit(USB_SERIAL_THROTTLED, &port->flags)) + return; + + usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); @@ -485,23 +475,16 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); void usb_serial_generic_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); - port->throttle_req = 1; - spin_unlock_irqrestore(&port->lock, flags); + set_bit(USB_SERIAL_THROTTLED, &port->flags); } EXPORT_SYMBOL_GPL(usb_serial_generic_throttle); void usb_serial_generic_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int was_throttled; - spin_lock_irq(&port->lock); - was_throttled = port->throttled; - port->throttled = port->throttle_req = 0; - spin_unlock_irq(&port->lock); + clear_bit(USB_SERIAL_THROTTLED, &port->flags); /* * Matches the smp_mb__after_atomic() in @@ -509,8 +492,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) */ smp_mb(); - if (was_throttled) - usb_serial_generic_submit_read_urbs(port, GFP_KERNEL); + usb_serial_generic_submit_read_urbs(port, GFP_KERNEL); } EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 1c19f77ed541..d8bdab8f3c26 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -28,6 +28,7 @@ /* USB serial flags */ #define USB_SERIAL_WRITE_BUSY 0 +#define USB_SERIAL_THROTTLED 1 /** * usb_serial_port: structure for the specific ports of a device. @@ -67,8 +68,6 @@ * @flags: usb serial port flags * @write_wait: a wait_queue_head_t used by the port. * @work: work queue entry for the line discipline waking up. - * @throttled: nonzero if the read urb is inactive to throttle the device - * @throttle_req: nonzero if the tty wants to throttle us * @dev: pointer to the serial device * * This structure is used by the usb-serial core and drivers for the specific @@ -115,8 +114,6 @@ struct usb_serial_port { unsigned long flags; wait_queue_head_t write_wait; struct work_struct work; - char throttled; - char throttle_req; unsigned long sysrq; /* sysrq timeout */ struct device dev; }; From patchwork Thu Apr 25 16:05:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 10917439 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C9B12933 for ; Thu, 25 Apr 2019 16:06:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BAC3128C04 for ; Thu, 25 Apr 2019 16:06:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AF3D228C91; Thu, 25 Apr 2019 16:06:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 218CB28C04 for ; Thu, 25 Apr 2019 16:06:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726985AbfDYQGB (ORCPT ); Thu, 25 Apr 2019 12:06:01 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:44861 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726386AbfDYQGA (ORCPT ); Thu, 25 Apr 2019 12:06:00 -0400 Received: by mail-lf1-f66.google.com with SMTP id h18so45242lfj.11 for ; Thu, 25 Apr 2019 09:05:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZuYnVLOOM0aJRCaFJiR4GrjUKAaf0bn66ZhgVFINsqE=; b=pC1xuosFLUpAjbS1EENjD03/GznnyOsQ8d5aFhrvHPYqI+Jc1tLwmPSjvJfpuLp9S5 oSY6VF3uZZqe19ggmI6HaGGmLPOcI3WUH1CsPIn48fVr99f3WeVcFS+zMTD83BxiJuyO cT/0WBSUd1M6ay2iXBSz+RfKpeB8OIrc3Bu9HfTNQQfqCyxBjTuW/XIRL1XBZd2iAzl8 xokvu9Jwzxd2hQl4LFNyhUx//U8pHRHMA91roomhAmpk08wgQ+q6F6WrvG5PZTTEvB66 QrtKnUQeqKHwIupRBamfgbFtXipgwZ99aeEtKsKHqxLtTdXlEb2aOm//h/KuvKDfdN0a KVBA== X-Gm-Message-State: APjAAAXdrtJ9u7JzRNFrMlVXyihF5pdnNUqucUOftnj21dZnoKdgPpin kpRyWB2X/KluBuGFtFsKd/K/UDZM X-Google-Smtp-Source: APXvYqwrzhfF9xymPgYHOsRbKaoA5s/hComJ3EuheyA6GB3VTh5SiWmnyy2bQrEIqH/Mrd0cggyYlw== X-Received: by 2002:ac2:43d8:: with SMTP id u24mr21373588lfl.94.1556208358530; Thu, 25 Apr 2019 09:05:58 -0700 (PDT) Received: from xi.terra (c-74bee655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.190.116]) by smtp.gmail.com with ESMTPSA id m24sm1056237ljb.67.2019.04.25.09.05.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Apr 2019 09:05:56 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1hJgsl-0002ct-Or; Thu, 25 Apr 2019 18:05:55 +0200 From: Johan Hovold To: Alan Stern , Oliver Neukum , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, Johan Hovold Subject: [PATCH 3/5] USB: serial: generic: drop unnecessary goto Date: Thu, 25 Apr 2019 18:05:38 +0200 Message-Id: <20190425160540.10036-4-johan@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190425160540.10036-1-johan@kernel.org> References: <20190425160540.10036-1-johan@kernel.org> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Drop an unnecessary goto from a write-urb completion error path. Signed-off-by: Johan Hovold --- drivers/usb/serial/generic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 67cef3ef1e5f..1be8bea372a2 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -463,10 +463,9 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) default: dev_err_console(port, "%s - nonzero urb status: %d\n", __func__, status); - goto resubmit; + break; } -resubmit: usb_serial_generic_write_start(port, GFP_ATOMIC); usb_serial_port_softint(port); } From patchwork Thu Apr 25 16:05:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 10917441 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8D16D76 for ; Thu, 25 Apr 2019 16:06:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7D75028C04 for ; Thu, 25 Apr 2019 16:06:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 71CEE28C91; Thu, 25 Apr 2019 16:06:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 068E728C04 for ; Thu, 25 Apr 2019 16:06:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727032AbfDYQGB (ORCPT ); Thu, 25 Apr 2019 12:06:01 -0400 Received: from mail-lj1-f193.google.com ([209.85.208.193]:41257 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726402AbfDYQGB (ORCPT ); Thu, 25 Apr 2019 12:06:01 -0400 Received: by mail-lj1-f193.google.com with SMTP id k8so121469lja.8 for ; Thu, 25 Apr 2019 09:06:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ghd5sen29/Bi74U3Gibs4OW/k3IhJ+8hQMPkcoDoczs=; b=sULMexuYYmaTkwh2n5yNuiT0uTmKAqGvYLxBSzyOdM2oAyNJMOGdwVovp+Gf2L+iC+ QnIeLttSIuzxtwBwSoqtZ1OoNBSjYgl41eMCf7MLqxr0pwqU7JaKGpmP3zXlgyBN5SVu enq6jk89abUDC6vmW1tj8p370BJTie3kx81fJXDVyZDbEfN7hc2kpP+/nb4u23Zl1XNM kU1BhPT/oaJbVrklqz8+xOn/fFHlI91bIplaiieuF9EgqMgiED//3AWDoqdZnVVowInF gvZ77nik6RFepkcMYBjwxXv7mfYIf6YXa0qUy1qFh/iLvrxd9udb+aTIEqhw9idDKwfd iWIQ== X-Gm-Message-State: APjAAAVicnayG+wl4j+zzVmSCGxu0huYwa0KdPOoS9GcDT3Ch5PzV9LI 5HTHsfexpFZ1AZcVorTb49aT9R0c X-Google-Smtp-Source: APXvYqxmXUVq7EWVhdoLUxvlv9dd1RbbpxAbKfu+86pX1OFvSdR6a2/y1P5bJ/Sj1sUC9inQKCsMjw== X-Received: by 2002:a2e:7503:: with SMTP id q3mr21024994ljc.190.1556208359444; Thu, 25 Apr 2019 09:05:59 -0700 (PDT) Received: from xi.terra (c-74bee655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.190.116]) by smtp.gmail.com with ESMTPSA id 63sm5132277lfz.2.2019.04.25.09.05.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Apr 2019 09:05:57 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1hJgsl-0002cy-Ru; Thu, 25 Apr 2019 18:05:55 +0200 From: Johan Hovold To: Alan Stern , Oliver Neukum , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, Johan Hovold Subject: [PATCH 4/5] USB: cdc-acm: fix unthrottle races Date: Thu, 25 Apr 2019 18:05:39 +0200 Message-Id: <20190425160540.10036-5-johan@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190425160540.10036-1-johan@kernel.org> References: <20190425160540.10036-1-johan@kernel.org> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Fix two long-standing bugs which could potentially lead to memory corruption or leave the port throttled until it is reopened (on weakly ordered systems), respectively, when read-URB completion races with unthrottle(). First, the URB must not be marked as free before processing is complete to prevent it from being submitted by unthrottle() on another CPU. CPU 1 CPU 2 ================ ================ complete() unthrottle() process_urb(); smp_mb__before_atomic(); set_bit(i, free); if (test_and_clear_bit(i, free)) submit_urb(); Second, the URB must be marked as free before checking the throttled flag to prevent unthrottle() on another CPU from failing to observe that the URB needs to be submitted if complete() sees that the throttled flag is set. CPU 1 CPU 2 ================ ================ complete() unthrottle() set_bit(i, free); throttled = 0; smp_mb__after_atomic(); smp_mb(); if (throttled) if (test_and_clear_bit(i, free)) return; submit_urb(); Note that test_and_clear_bit() only implies barriers when the test is successful. To handle the case where the URB is still in use an explicit barrier needs to be added to unthrottle() for the second race condition. Also note that the first race was fixed by 36e59e0d70d6 ("cdc-acm: fix race between callback and unthrottle") back in 2015, but the bug was reintroduced a year later. Fixes: 1aba579f3cf5 ("cdc-acm: handle read pipe errors") Fixes: 088c64f81284 ("USB: cdc-acm: re-write read processing") Signed-off-by: Johan Hovold Acked-by: Oliver Neukum --- drivers/usb/class/cdc-acm.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ec666eb4b7b4..c03aa8550980 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -470,12 +470,12 @@ static void acm_read_bulk_callback(struct urb *urb) struct acm *acm = rb->instance; unsigned long flags; int status = urb->status; + bool stopped = false; + bool stalled = false; dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n", rb->index, urb->actual_length, status); - set_bit(rb->index, &acm->read_urbs_free); - if (!acm->dev) { dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); return; @@ -488,15 +488,16 @@ static void acm_read_bulk_callback(struct urb *urb) break; case -EPIPE: set_bit(EVENT_RX_STALL, &acm->flags); - schedule_work(&acm->work); - return; + stalled = true; + break; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: dev_dbg(&acm->data->dev, "%s - urb shutting down with status: %d\n", __func__, status); - return; + stopped = true; + break; default: dev_dbg(&acm->data->dev, "%s - nonzero urb status received: %d\n", @@ -505,10 +506,24 @@ static void acm_read_bulk_callback(struct urb *urb) } /* - * Unthrottle may run on another CPU which needs to see events - * in the same order. Submission has an implict barrier + * Make sure URB processing is done before marking as free to avoid + * racing with unthrottle() on another CPU. Matches the barriers + * implied by the test_and_clear_bit() in acm_submit_read_urb(). */ smp_mb__before_atomic(); + set_bit(rb->index, &acm->read_urbs_free); + /* + * Make sure URB is marked as free before checking the throttled flag + * to avoid racing with unthrottle() on another CPU. Matches the + * smp_mb() in unthrottle(). + */ + smp_mb__after_atomic(); + + if (stopped || stalled) { + if (stalled) + schedule_work(&acm->work); + return; + } /* throttle device if requested by tty */ spin_lock_irqsave(&acm->read_lock, flags); @@ -842,6 +857,9 @@ static void acm_tty_unthrottle(struct tty_struct *tty) acm->throttle_req = 0; spin_unlock_irq(&acm->read_lock); + /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */ + smp_mb(); + if (was_throttled) acm_submit_read_urbs(acm, GFP_KERNEL); } From patchwork Thu Apr 25 16:05:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johan Hovold X-Patchwork-Id: 10917445 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C3CD976 for ; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5A9328BD5 for ; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A99E328C29; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A51E28BD5 for ; Thu, 25 Apr 2019 16:06:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726402AbfDYQGD (ORCPT ); Thu, 25 Apr 2019 12:06:03 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:39346 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726859AbfDYQGC (ORCPT ); Thu, 25 Apr 2019 12:06:02 -0400 Received: by mail-lf1-f66.google.com with SMTP id d12so180212lfk.6 for ; Thu, 25 Apr 2019 09:06:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jCrLocsed8C23l/Qz2ceGAv+q7KSLARapoD49XZWHrQ=; b=iovlPOjODV4vxWQrn3RW2HU+TJP6scdGSFr/OpDMux3KrA0s+ZGzOZN7qsTvLu3JeW s40nan/Uv9ze5IVzOkaslSRrDAAOc1N2dxFdSvfVwvQM8hzfCoOYw864IQnI++2CloyQ Shcnb71nK0p2H3HbY4pacmY0WJXhF0xCwAAHyKYgVecVjSIzZK5JnScYwQ3vYLbA03zs 8cEGJq9FVSLvW2ihOl7mMCuwctbeqi2d1YVmvOZv6BYfOyiGtqGaURv1xmf/rVkdv2KI LZpCjpzgVFe+RpbqmkXbWqJpAVjiNwWcXRyy3YYFakGP1+q6F05+qxXLyuaNE6gLQHfT stYQ== X-Gm-Message-State: APjAAAWVUFF2h7QTYkvpqdnDIxBEQlCFwyMuVs+KbU0GJkxuNBZBXy3Z brGUBCiiq1tN2ePiEVqtQZs= X-Google-Smtp-Source: APXvYqzsI6XUtV5eu1qIxgC62mhxzk54ojfu5u/J12gYUrY1ZvdurG1U4EaGK6nxAwIUMe60LA+Nqg== X-Received: by 2002:ac2:558d:: with SMTP id v13mr14895265lfg.76.1556208359981; Thu, 25 Apr 2019 09:05:59 -0700 (PDT) Received: from xi.terra (c-74bee655.07-184-6d6c6d4.bbcust.telenor.se. [85.230.190.116]) by smtp.gmail.com with ESMTPSA id l16sm4733160ljb.24.2019.04.25.09.05.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Apr 2019 09:05:57 -0700 (PDT) Received: from johan by xi.terra with local (Exim 4.91) (envelope-from ) id 1hJgsl-0002d3-UK; Thu, 25 Apr 2019 18:05:55 +0200 From: Johan Hovold To: Alan Stern , Oliver Neukum , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, Johan Hovold Subject: [PATCH 5/5] USB: cdc-acm: clean up throttle handling Date: Thu, 25 Apr 2019 18:05:40 +0200 Message-Id: <20190425160540.10036-6-johan@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190425160540.10036-1-johan@kernel.org> References: <20190425160540.10036-1-johan@kernel.org> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Clean up the throttle implementation by dropping the redundant throttle_req flag which was a remnant from back when USB serial had only a single read URB, something which was later carried over to cdc-acm. Also convert the throttled flag to an atomic bit flag. Signed-off-by: Johan Hovold Acked-by: Oliver Neukum --- drivers/usb/class/cdc-acm.c | 33 ++++++++------------------------- drivers/usb/class/cdc-acm.h | 3 +-- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index c03aa8550980..183b41753c98 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -468,7 +468,6 @@ static void acm_read_bulk_callback(struct urb *urb) { struct acm_rb *rb = urb->context; struct acm *acm = rb->instance; - unsigned long flags; int status = urb->status; bool stopped = false; bool stalled = false; @@ -525,15 +524,10 @@ static void acm_read_bulk_callback(struct urb *urb) return; } - /* throttle device if requested by tty */ - spin_lock_irqsave(&acm->read_lock, flags); - acm->throttled = acm->throttle_req; - if (!acm->throttled) { - spin_unlock_irqrestore(&acm->read_lock, flags); - acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); - } else { - spin_unlock_irqrestore(&acm->read_lock, flags); - } + if (test_bit(ACM_THROTTLED, &acm->flags)) + return; + + acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); } /* data interface wrote those outgoing bytes */ @@ -670,10 +664,7 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) /* * Unthrottle device in case the TTY was closed while throttled. */ - spin_lock_irq(&acm->read_lock); - acm->throttled = 0; - acm->throttle_req = 0; - spin_unlock_irq(&acm->read_lock); + clear_bit(ACM_THROTTLED, &acm->flags); retval = acm_submit_read_urbs(acm, GFP_KERNEL); if (retval) @@ -841,27 +832,19 @@ static void acm_tty_throttle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - spin_lock_irq(&acm->read_lock); - acm->throttle_req = 1; - spin_unlock_irq(&acm->read_lock); + set_bit(ACM_THROTTLED, &acm->flags); } static void acm_tty_unthrottle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - unsigned int was_throttled; - spin_lock_irq(&acm->read_lock); - was_throttled = acm->throttled; - acm->throttled = 0; - acm->throttle_req = 0; - spin_unlock_irq(&acm->read_lock); + clear_bit(ACM_THROTTLED, &acm->flags); /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */ smp_mb(); - if (was_throttled) - acm_submit_read_urbs(acm, GFP_KERNEL); + acm_submit_read_urbs(acm, GFP_KERNEL); } static int acm_tty_break_ctl(struct tty_struct *tty, int state) diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 515aad0847ee..ca1c026382c2 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -108,6 +108,7 @@ struct acm { unsigned long flags; # define EVENT_TTY_WAKEUP 0 # define EVENT_RX_STALL 1 +# define ACM_THROTTLED 2 struct usb_cdc_line_coding line; /* bits, stop, parity */ struct work_struct work; /* work queue entry for line discipline waking up */ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ @@ -122,8 +123,6 @@ struct acm { unsigned int ctrl_caps; /* control capabilities from the class specific header */ unsigned int susp_count; /* number of suspended interfaces */ unsigned int combined_interfaces:1; /* control and data collapsed */ - unsigned int throttled:1; /* actually throttled */ - unsigned int throttle_req:1; /* throttle requested */ u8 bInterval; struct usb_anchor delayed; /* writes queued for a device about to be woken */ unsigned long quirks;