Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1762498AbXKPQ5t (ORCPT ); Fri, 16 Nov 2007 11:57:49 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756255AbXKPQ5a (ORCPT ); Fri, 16 Nov 2007 11:57:30 -0500 Received: from iolanthe.rowland.org ([192.131.102.54]:47193 "HELO iolanthe.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1755914AbXKPQ52 (ORCPT ); Fri, 16 Nov 2007 11:57:28 -0500 Date: Fri, 16 Nov 2007 11:57:28 -0500 (EST) From: Alan Stern X-X-Sender: stern@iolanthe.rowland.org To: Greg KH , David Woodhouse cc: USB development list , Kernel development list Subject: [PATCH] Driver core: fix race in __device_release_driver Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1659 Lines: 51 This patch (as1013) was suggested by David Woodhouse; it fixes a race in the driver core. If a device is unregistered at the same time as its driver is unloaded, the driver's code pages may be unmapped while the remove method is still running. The calls to get_driver() and put_driver() were intended to prevent this, but they don't work if the driver's module count has already dropped to 0. Instead, the patch keeps the device on the driver's list until after the remove method has returned. This forces the necessary synchronization to occur. Signed-off-by: Alan Stern CC: David Woodhouse --- This should be considered for 2.6.24. Index: usb-2.6/drivers/base/dd.c =================================================================== --- usb-2.6.orig/drivers/base/dd.c +++ usb-2.6/drivers/base/dd.c @@ -289,11 +289,10 @@ static void __device_release_driver(stru { struct device_driver * drv; - drv = get_driver(dev->driver); + drv = dev->driver; if (drv) { driver_sysfs_remove(dev); sysfs_remove_link(&dev->kobj, "driver"); - klist_remove(&dev->knode_driver); if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, @@ -306,7 +305,7 @@ static void __device_release_driver(stru drv->remove(dev); devres_release_all(dev); dev->driver = NULL; - put_driver(drv); + klist_remove(&dev->knode_driver); } } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/