From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754985Ab1ABHoJ (ORCPT ); Sun, 2 Jan 2011 02:44:09 -0500 Received: from mail.windriver.com ([147.11.1.11]:36355 "EHLO mail.windriver.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754411Ab1ABHY2 (ORCPT ); Sun, 2 Jan 2011 02:24:28 -0500 From: Paul Gortmaker To: stable@kernel.org, linux-kernel@vger.kernel.org Cc: stable-review@kernel.org, Alan Stern , Jiri Kosina , Greg Kroah-Hartman , Paul Gortmaker Subject: [34-longterm 165/260] USB: fix bug in initialization of interface minor numbers Date: Sun, 2 Jan 2011 02:17:41 -0500 Message-Id: <1293952756-15010-166-git-send-email-paul.gortmaker@windriver.com> X-Mailer: git-send-email 1.7.3.3 In-Reply-To: <1293952756-15010-1-git-send-email-paul.gortmaker@windriver.com> References: <1293952756-15010-1-git-send-email-paul.gortmaker@windriver.com> X-OriginalArrivalTime: 02 Jan 2011 07:23:11.0181 (UTC) FILETIME=[E932B7D0:01CBAA4D] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alan Stern commit 0026e00523a85b90a92a93ddf6660939ecef3e54 upstream. Recent changes in the usbhid layer exposed a bug in usbcore. If CONFIG_USB_DYNAMIC_MINORS is enabled then an interface may be assigned a minor number of 0. However interfaces that aren't registered as USB class devices also have their minor number set to 0, during initialization. As a result usb_find_interface() may return the wrong interface, leading to a crash. This patch (as1418) fixes the problem by initializing every interface's minor number to -1. It also cleans up the usb_register_dev() function, which besides being somewhat awkwardly written, does not unwind completely on all its error paths. Signed-off-by: Alan Stern Tested-by: Philip J. Turmel Tested-by: Gabriel Craciunescu Tested-by: Alex Riesen Tested-by: Matthias Bayer CC: Jiri Kosina Signed-off-by: Greg Kroah-Hartman Signed-off-by: Paul Gortmaker --- drivers/usb/core/file.c | 35 ++++++++++++++++------------------- drivers/usb/core/message.c | 1 + 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index f06f5db..1e6ccef 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -159,9 +159,9 @@ void usb_major_cleanup(void) int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { - int retval = -EINVAL; + int retval; int minor_base = class_driver->minor_base; - int minor = 0; + int minor; char name[20]; char *temp; @@ -173,12 +173,17 @@ int usb_register_dev(struct usb_interface *intf, */ minor_base = 0; #endif - intf->minor = -1; - - dbg ("looking for a minor, starting at %d", minor_base); if (class_driver->fops == NULL) - goto exit; + return -EINVAL; + if (intf->minor >= 0) + return -EADDRINUSE; + + retval = init_usb_class(); + if (retval) + return retval; + + dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base); down_write(&minor_rwsem); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { @@ -186,20 +191,12 @@ int usb_register_dev(struct usb_interface *intf, continue; usb_minors[minor] = class_driver->fops; - - retval = 0; + intf->minor = minor; break; } up_write(&minor_rwsem); - - if (retval) - goto exit; - - retval = init_usb_class(); - if (retval) - goto exit; - - intf->minor = minor; + if (intf->minor < 0) + return -EXFULL; /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); @@ -213,11 +210,11 @@ int usb_register_dev(struct usb_interface *intf, "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); - usb_minors[intf->minor] = NULL; + usb_minors[minor] = NULL; + intf->minor = -1; up_write(&minor_rwsem); retval = PTR_ERR(intf->usb_dev); } -exit: return retval; } EXPORT_SYMBOL_GPL(usb_register_dev); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 794dca2..ad1f359 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1817,6 +1817,7 @@ free_interfaces: intf->dev.groups = usb_interface_groups; intf->dev.dma_mask = dev->dev.dma_mask; INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); + intf->minor = -1; device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, -- 1.7.3.3