From patchwork Wed May 27 21:56:58 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Len Brown X-Patchwork-Id: 26640 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n4RMfwio017139 for ; Wed, 27 May 2009 22:41:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758325AbZE0Wld (ORCPT ); Wed, 27 May 2009 18:41:33 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755808AbZE0Wlc (ORCPT ); Wed, 27 May 2009 18:41:32 -0400 Received: from vms173001pub.verizon.net ([206.46.173.1]:9100 "EHLO vms173001pub.verizon.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758401AbZE0Wlb (ORCPT ); Wed, 27 May 2009 18:41:31 -0400 Received: from localhost.localdomain ([98.118.45.40]) by vms173001.mailsrvcs.net (Sun Java(tm) System Messaging Server 6.3-7.04 (built Sep 26 2008; 32bit)) with ESMTPA id <0KKB004N4OZ0QGZ6@vms173001.mailsrvcs.net>; Wed, 27 May 2009 16:57:00 -0500 (CDT) Received: from localhost.localdomain (d975xbx2 [127.0.0.1]) by localhost.localdomain (8.14.2/8.14.2) with ESMTP id n4RLuxaX025842; Wed, 27 May 2009 17:56:59 -0400 Received: from localhost (lenb@localhost) by localhost.localdomain (8.14.2/8.14.2/Submit) with ESMTP id n4RLuwwc025837; Wed, 27 May 2009 17:56:58 -0400 X-Authentication-warning: localhost.localdomain: lenb owned process doing -bs Date: Wed, 27 May 2009 17:56:58 -0400 (EDT) From: Len Brown X-X-Sender: lenb@localhost.localdomain To: Kenji Kaneshige Cc: Alex Chiang , Bjorn Helgaas , "linux-pci@vger.kernel.org" , Jesse Barnes , linux acpi Subject: Re: [PATCH] PCI/ACPI: fix wrong ref count handling in acpi_pci_bind() In-reply-to: <4A1C8208.6090707@jp.fujitsu.com> Message-id: References: <4A1B32E3.7060801@jp.fujitsu.com> <200905260946.02184.bjorn.helgaas@hp.com> <20090526234148.GA12468@ldl.fc.hp.com> <4A1C8208.6090707@jp.fujitsu.com> User-Agent: Alpine 2.00 (LFD 1167 2008-08-23) MIME-version: 1.0 Content-type: TEXT/PLAIN; charset=US-ASCII Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From dacd2549ca61ddbdd1ed62a76ca95dea3f0e02c6 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 26 May 2009 09:08:03 +0900 Subject: [PATCH] PCI/ACPI: fix wrong ref count handling in acpi_pci_bind() The 'dev' field of struct acpi_pci_data is having a pointer to struct pci_dev without incrementing the reference counter. Because of this, I got the following kernel oops when I was doing some pci hotplug operations. This patch fixes this bug by replacing wrong hand-made pci_find_slot() with pci_get_slot() in acpi_pci_bind(). BUG: unable to handle kernel NULL pointer dereference at 00000000000000e8 IP: [] acpi_pci_unbind+0xb1/0xdd Call Trace: [] acpi_bus_remove+0x54/0x68 [] acpi_bus_trim+0x75/0xe3 [] acpiphp_disable_slot+0x16d/0x1e0 [acpiphp] [] disable_slot+0x20/0x60 [acpiphp] [] power_write_file+0xc8/0x110 [] pci_slot_attr_store+0x24/0x30 [] sysfs_write_file+0xce/0x140 [] vfs_write+0xc7/0x170 [] sys_write+0x50/0x90 [] system_call_fastpath+0x16/0x1b Signed-off-by: Kenji Kaneshige Reviewed-by: Bjorn Helgaas Reviewed-by: Alex Chiang Tested-by: Alex Chiang Signed-off-by: Len Brown --- as applied to the acpi tree... cheers, -Len drivers/acpi/pci_bind.c | 24 ++++++------------------ 1 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 95650f8..bc46de3 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -116,9 +116,6 @@ int acpi_pci_bind(struct acpi_device *device) struct acpi_pci_data *pdata; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle; - struct pci_dev *dev; - struct pci_bus *bus; - if (!device || !device->parent) return -EINVAL; @@ -176,20 +173,9 @@ int acpi_pci_bind(struct acpi_device *device) * Locate matching device in PCI namespace. If it doesn't exist * this typically means that the device isn't currently inserted * (e.g. docking station, port replicator, etc.). - * We cannot simply search the global pci device list, since - * PCI devices are added to the global pci list when the root - * bridge start ops are run, which may not have happened yet. */ - bus = pci_find_bus(data->id.segment, data->id.bus); - if (bus) { - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->devfn == PCI_DEVFN(data->id.device, - data->id.function)) { - data->dev = dev; - break; - } - } - } + data->dev = pci_get_slot(pdata->bus, + PCI_DEVFN(data->id.device, data->id.function)); if (!data->dev) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d not present in PCI namespace\n", @@ -259,9 +245,10 @@ int acpi_pci_bind(struct acpi_device *device) end: kfree(buffer.pointer); - if (result) + if (result) { + pci_dev_put(data->dev); kfree(data); - + } return result; } @@ -303,6 +290,7 @@ static int acpi_pci_unbind(struct acpi_device *device) if (data->dev->subordinate) { acpi_pci_irq_del_prt(data->id.segment, data->bus->number); } + pci_dev_put(data->dev); kfree(data); end: