linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: ACPI Devel Maling List <linux-acpi@vger.kernel.org>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Aaron Lu <aaron.lu@intel.com>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>
Subject: [PATCH 4/24][New] ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event()
Date: Tue, 04 Feb 2014 00:18:03 +0100	[thread overview]
Message-ID: <1460941.uPM2Zn8FLA@vostro.rjw.lan> (raw)
In-Reply-To: <7532948.aJNUotNMpR@vostro.rjw.lan>

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

If a PCI bridge with an ACPIPHP context attached is removed via
sysfs, the code path executed as a result is the following:

pci_stop_and_remove_bus_device_locked
 pci_remove_bus
  pcibios_remove_bus
   acpi_pci_remove_bus
    acpiphp_remove_slots
     cleanup_bridge
     put_bridge
      free_bridge
       acpiphp_put_context (for each child, under context lock)
        kfree (child context)

Now, if a hotplug notify is dispatched for one of the bridge's
children and the timing is such that handle_hotplug_event() for
that notify is executed while free_bridge() above is running,
the get_bridge(context->func.parent) in handle_hotplug_event()
will not really help, because it is too late to prevent the bridge
from going away and the child's context may be freed before
hotplug_event_work() scheduled from handle_hotplug_event()
dereferences the pointer to it passed via the data argument.
That will cause a kernel crash to happpen in hotplug_event_work().

To prevent that from happening, make handle_hotplug_event()
check the is_going_away flag of the function's parent bridge
(under acpiphp_context_lock) and bail out if it's set.  Also,
make cleanup_bridge() set the bridge's is_going_away flag under
acpiphp_context_lock so that it cannot be changed between the
check and the subsequent get_bridge(context->func.parent) in
handle_hotplug_event().

Then, in the above scenario, handle_hotplug_event() will notice
that context->func.parent->is_going_away is already set and it
will exit immediately preventing the crash from happening.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -441,7 +441,9 @@ static void cleanup_bridge(struct acpiph
 	list_del(&bridge->list);
 	mutex_unlock(&bridge_mutex);
 
+	mutex_lock(&acpiphp_context_lock);
 	bridge->is_going_away = true;
+	mutex_unlock(&acpiphp_context_lock);
 }
 
 /**
@@ -941,6 +943,7 @@ static void handle_hotplug_event(acpi_ha
 {
 	struct acpiphp_context *context;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
+	acpi_status status;
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
@@ -976,13 +979,20 @@ static void handle_hotplug_event(acpi_ha
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->handle != handle)) {
-		get_bridge(context->func.parent);
-		acpiphp_put_context(context);
-		acpi_hotplug_execute(hotplug_event_work, context, type);
+	if (!context || WARN_ON(context->handle != handle)
+	    || context->func.parent->is_going_away)
+		goto err_out;
+
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
+	status = acpi_hotplug_execute(hotplug_event_work, context, type);
+	if (ACPI_SUCCESS(status)) {
 		mutex_unlock(&acpiphp_context_lock);
 		return;
 	}
+	put_bridge(context->func.parent);
+
+ err_out:
 	mutex_unlock(&acpiphp_context_lock);
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 


  parent reply	other threads:[~2014-02-03 23:28 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
2014-01-27  0:38 ` [PATCH 1/11] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
2014-01-27  0:38 ` [PATCH 2/11] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
2014-01-27  0:39 ` [PATCH 3/11] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
2014-01-27  0:40 ` [PATCH 4/11] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
2014-01-27  0:41 ` [PATCH 5/11] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
2014-01-27  0:41 ` [PATCH 6/11] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
2014-01-27  0:42 ` [PATCH 7/11] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
2014-01-27  0:43 ` [PATCH 8/11] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
2014-01-27  0:44 ` [PATCH 9/11] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
2014-01-27  0:45 ` [PATCH 10/11] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
2014-01-27  0:46 ` [PATCH 11/11] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-01-28 22:12   ` [PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
2014-01-28 22:13   ` [PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-28 22:14   ` [PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-01-28 22:14   ` [PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-28 22:16   ` [PATCH 5/5][RFT] ACPI / hotplug: Dispach hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-01-28 23:58     ` [Resend][PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
2014-01-28 23:59     ` [Resend][PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-28 23:59     ` [Update][PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-01-29  0:00     ` [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-31 15:28       ` Mika Westerberg
2014-01-31 15:42         ` Rafael J. Wysocki
2014-01-31 15:40           ` Mika Westerberg
2014-01-31 16:01             ` Mika Westerberg
2014-01-31 16:16               ` Rafael J. Wysocki
2014-01-31 17:09                 ` Mika Westerberg
2014-01-31 17:34                   ` Rafael J. Wysocki
2014-02-02  0:12                     ` Rafael J. Wysocki
2014-01-29  0:02     ` [Update][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-01-30 15:28       ` [Update 2x][PATCH " Rafael J. Wysocki
2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-02-02  0:54       ` [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb() Rafael J. Wysocki
2014-02-02 17:01         ` Rafael J. Wysocki
2014-02-02  0:55       ` [PATCH v2 2/6] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
2014-02-02  0:56       ` [PATCH v2 3/6] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-02-02  0:57       ` [PATCH v2 4/6] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
2014-02-02  0:58       ` [PATCH v2 5/6] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-02-02  0:58       ` [PATCH v2 6/6] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-02-02 17:12         ` [PATCH v3 1/7] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
2014-02-02 17:15         ` [PATCH v3 2/7] ACPI / hotplug: Fix potential races in notify handlers Rafael J. Wysocki
2014-02-02 17:16         ` [PATCH v3 3/7] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
2014-02-02 17:17         ` [PATCH v3 4/7] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-02-02 17:18         ` [PATCH v3 5/7] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
2014-02-02 17:19         ` [PATCH v3 6/7] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-02-02 17:20         ` [PATCH v3 7/7] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-02-03 10:45         ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Mika Westerberg
2014-02-03 21:51           ` Rafael J. Wysocki
2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
2014-02-02  0:21   ` [PATCH v2 1/13] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
2014-02-02  0:22   ` [PATCH v2 2/13] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
2014-02-02  0:23   ` [PATCH v2 3/13] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
2014-02-02  0:24   ` [PATCH v2 4/13] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
2014-02-02  0:25   ` [PATCH v2 5/13] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
2014-02-02  0:26   ` [PATCH v2 6/13] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
2014-02-02  0:27   ` [PATCH v2 7/13] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
2014-02-02  0:27   ` [PATCH v2 8/13] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
2014-02-02  0:28   ` [PATCH v2 9/13] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
2014-02-02  0:29   ` [PATCH v2 10/13] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
2014-02-02  0:30   ` [PATCH v2 11/13] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
2014-02-02  0:31   ` [PATCH v2 12/13] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
2014-02-02  0:31   ` [PATCH v2 13/13] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
2014-02-03  1:47   ` [PATCH] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
2014-02-03 10:44   ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Mika Westerberg
2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
2014-02-03 23:14       ` [PATCH 1/24][Resend] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
2014-02-03 23:15       ` [PATCH 2/24][Resend] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
2014-02-03 23:16       ` [PATCH 3/24][Resend] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
2014-02-03 23:18       ` Rafael J. Wysocki [this message]
2014-02-03 23:18       ` [PATCH 5/24][New] ACPI / hotplug / PCI: Fix bridge removal race vs dock events Rafael J. Wysocki
2014-02-03 23:20       ` [PATCH 6/24][Resend] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
2014-02-03 23:21       ` [PATCH 7/24][Resend] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
2014-02-03 23:22       ` [PATCH 8/24][Resend] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
2014-02-03 23:23       ` [PATCH 9/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
2014-02-03 23:24       ` [PATCH 10/24][Resend] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
2014-02-03 23:25       ` [PATCH 11/24][Update] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
2014-02-03 23:26       ` [PATCH 12/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
2014-02-03 23:27       ` [PATCH 13/24][Resend] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
2014-02-03 23:33       ` [PATCH 14/24][Update] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
2014-02-03 23:33       ` [PATCH 15/24][Resend] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
2014-02-03 23:34       ` [PATCH 16/24][New] ACPI / hotplug / PCI: Do not pass ACPI handle to hotplug_event() Rafael J. Wysocki
2014-02-03 23:34       ` [PATCH 17/24][Resend] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
2014-02-03 23:36       ` [PATCH 18/24][Update] ACPI / hotplug: Fix potential race in acpi_bus_notify() Rafael J. Wysocki
2014-02-03 23:36       ` [PATCH 19/24][Update] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
2014-02-03 23:37       ` [PATCH 20/24][Update] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-02-06 13:07         ` [Update][PATCH 20/24] " Rafael J. Wysocki
2014-02-06 23:35           ` [Update 2x][PATCH " Rafael J. Wysocki
2014-02-03 23:38       ` [PATCH 21/24][Resend] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
2014-02-03 23:39       ` [PATCH 22/24][Resend] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-02-06 13:09         ` [Update][PATCH 22/24] " Rafael J. Wysocki
2014-02-03 23:40       ` [PATCH 23/24][Update] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-02-06 13:10         ` [Update][PATCH 23/24] " Rafael J. Wysocki
2014-02-03 23:41       ` [PATCH 24/24][New] ACPI / hotplug / PCI: Rework acpiphp_check_host_bridge() Rafael J. Wysocki
2014-02-05 10:14       ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Mika Westerberg
2014-02-05 10:59         ` Rafael J. Wysocki
2014-02-11  0:19 ` [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Bjorn Helgaas
2014-02-11 12:53   ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1460941.uPM2Zn8FLA@vostro.rjw.lan \
    --to=rjw@rjwysocki.net \
    --cc=aaron.lu@intel.com \
    --cc=bhelgaas@google.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).