From patchwork Wed Feb 17 17:37:05 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Whitcroft X-Patchwork-Id: 45647 X-Patchwork-Delegate: apw@canonical.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id E52AFB7C7E for ; Thu, 18 Feb 2010 04:37:15 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1Nhnpk-0001LB-Kv; Wed, 17 Feb 2010 17:37:08 +0000 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1Nhnpi-0001JU-Sn for kernel-team@lists.ubuntu.com; Wed, 17 Feb 2010 17:37:07 +0000 Received: from hutte.canonical.com ([91.189.90.181]) by adelie.canonical.com with esmtp (Exim 4.69 #1 (Debian)) id 1Nhnpi-00087a-RB for ; Wed, 17 Feb 2010 17:37:06 +0000 Received: from 79-66-190-238.dynamic.dsl.as9105.com ([79.66.190.238] helo=localhost.localdomain) by hutte.canonical.com with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1Nhnpi-0003Em-LT for kernel-team@lists.ubuntu.com; Wed, 17 Feb 2010 17:37:06 +0000 From: Andy Whitcroft To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/1] UBUNTU: SAUCE: khubd -- switch USB product/manufacturer/serial handling to RCU Date: Wed, 17 Feb 2010 17:37:05 +0000 Message-Id: <1266428225-31549-2-git-send-email-apw@canonical.com> X-Mailer: git-send-email 1.6.6.1 In-Reply-To: <1266428225-31549-1-git-send-email-apw@canonical.com> References: <1266428225-31549-1-git-send-email-apw@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com BugLink: http://bugs.launchpad.net/bugs/510937 With the introduction of wireless USB hubs the product, manufacturer, and serial number are now mutable. This necessitates new locking in the consumers of these values including the sysfs read routines in order to prevent use-after-free acces to these values. These extra locks create significant lock contention leading to increased boot times (0.3s for an example Atom based system). Move update of these values to RCU based locking. Signed-off-by: Andy Whitcroft --- drivers/usb/core/hub.c | 34 ++++++++++++++++++++++++++++------ drivers/usb/core/sysfs.c | 6 +++--- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1a7d54b..75804a9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -1803,6 +1804,10 @@ fail: */ int usb_deauthorize_device(struct usb_device *usb_dev) { + char *product = NULL; + char *manufacturer = NULL; + char *serial = NULL; + usb_lock_device(usb_dev); if (usb_dev->authorized == 0) goto out_unauthorized; @@ -1810,11 +1815,12 @@ int usb_deauthorize_device(struct usb_device *usb_dev) usb_dev->authorized = 0; usb_set_configuration(usb_dev, -1); - kfree(usb_dev->product); + product = usb_dev->product; + manufacturer = usb_dev->manufacturer; + serial = usb_dev->serial; + usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->manufacturer); usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->serial); usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); usb_destroy_configuration(usb_dev); @@ -1822,6 +1828,12 @@ int usb_deauthorize_device(struct usb_device *usb_dev) out_unauthorized: usb_unlock_device(usb_dev); + if (product || manufacturer || serial) { + synchronize_rcu(); + kfree(product); + kfree(manufacturer); + kfree(serial); + } return 0; } @@ -1829,6 +1841,9 @@ out_unauthorized: int usb_authorize_device(struct usb_device *usb_dev) { int result = 0, c; + char *product = NULL; + char *manufacturer = NULL; + char *serial = NULL; usb_lock_device(usb_dev); if (usb_dev->authorized == 1) @@ -1847,11 +1862,12 @@ int usb_authorize_device(struct usb_device *usb_dev) goto error_device_descriptor; } - kfree(usb_dev->product); + + product = usb_dev->product; usb_dev->product = NULL; - kfree(usb_dev->manufacturer); + manufacturer = usb_dev->manufacturer; usb_dev->manufacturer = NULL; - kfree(usb_dev->serial); + serial = usb_dev->serial; usb_dev->serial = NULL; usb_dev->authorized = 1; @@ -1879,6 +1895,12 @@ error_device_descriptor: error_autoresume: out_authorized: usb_unlock_device(usb_dev); // complements locktree + if (product || manufacturer || serial) { + synchronize_rcu(); + kfree(product); + kfree(manufacturer); + kfree(serial); + } return result; } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index fcdcad4..25d2fa7 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -85,9 +85,9 @@ static ssize_t show_##name(struct device *dev, \ int retval; \ \ udev = to_usb_device(dev); \ - usb_lock_device(udev); \ - retval = sprintf(buf, "%s\n", udev->name); \ - usb_unlock_device(udev); \ + rcu_read_lock(); \ + retval = sprintf(buf, "%s\n", rcu_dereference(udev->name)); \ + rcu_read_unlock(); \ return retval; \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);