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 18/24][Update] ACPI / hotplug: Fix potential race in acpi_bus_notify()
Date: Tue, 04 Feb 2014 00:36:10 +0100 [thread overview]
Message-ID: <1957606.iEkqlTBjjf@vostro.rjw.lan> (raw)
In-Reply-To: <7532948.aJNUotNMpR@vostro.rjw.lan>
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
There is a slight possibility for the ACPI device object pointed to
by adev in acpi_hotplug_notify_cb() to become invalid between the
acpi_bus_get_device() that it comes from and the subsequent dereference
of that pointer under get_device(). Namely, if acpi_scan_drop_device()
runs in parallel with acpi_hotplug_notify_cb(), acpi_device_del_work_fn()
queued up by it may delete the device object in question right after
a successful execution of acpi_bus_get_device() in acpi_bus_notify().
An analogous problem is present in acpi_bus_notify() where the device
pointer coming from acpi_bus_get_device() may become invalid before
it subsequent dereference in the "if" block.
To prevent that from happening, introduce a new function,
acpi_bus_get_acpi_device(), working analogously to acpi_bus_get_device()
except that it will grab a reference to the ACPI device object returned
by it and it will do that under the ACPICA's namespace mutex. Then,
make both acpi_hotplug_notify_cb() and acpi_bus_notify() use
acpi_bus_get_acpi_device() instead of acpi_bus_get_device() so as to
ensure that the pointers used by them will not become stale at one
point.
In addition to that, introduce acpi_bus_put_acpi_device() as a wrapper
around put_device() to be used along with acpi_bus_get_acpi_device()
and make the (new) users of the latter use acpi_bus_put_acpi_device()
too.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/bus.c | 6 ++++--
drivers/acpi/scan.c | 42 ++++++++++++++++++++++++++++++++++--------
include/acpi/acpi_bus.h | 2 ++
3 files changed, 40 insertions(+), 10 deletions(-)
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -476,7 +476,7 @@ static void acpi_device_hotplug(void *da
out:
acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
- put_device(&adev->dev);
+ acpi_bus_put_acpi_device(adev);
mutex_unlock(&acpi_scan_lock);
unlock_device_hotplug();
}
@@ -488,9 +488,6 @@ static void acpi_hotplug_notify_cb(acpi_
struct acpi_device *adev;
acpi_status status;
- if (acpi_bus_get_device(handle, &adev))
- goto err_out;
-
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
@@ -512,12 +509,15 @@ static void acpi_hotplug_notify_cb(acpi_
/* non-hotplug event; possibly handled by other handler */
return;
}
- get_device(&adev->dev);
+ adev = acpi_bus_get_acpi_device(handle);
+ if (!adev)
+ goto err_out;
+
status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
if (ACPI_SUCCESS(status))
return;
- put_device(&adev->dev);
+ acpi_bus_put_acpi_device(adev);
err_out:
acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
@@ -1112,14 +1112,16 @@ static void acpi_scan_drop_device(acpi_h
mutex_unlock(&acpi_device_del_lock);
}
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device,
+ void (*callback)(void *))
{
acpi_status status;
if (!device)
return -EINVAL;
- status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device);
+ status = acpi_get_data_full(handle, acpi_scan_drop_device,
+ (void **)device, callback);
if (ACPI_FAILURE(status) || !*device) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
handle));
@@ -1127,8 +1129,32 @@ int acpi_bus_get_device(acpi_handle hand
}
return 0;
}
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+ return acpi_get_device_data(handle, device, NULL);
+}
EXPORT_SYMBOL(acpi_bus_get_device);
+static void get_acpi_device(void *dev)
+{
+ if (dev)
+ get_device(&((struct acpi_device *)dev)->dev);
+}
+
+struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
+{
+ struct acpi_device *adev = NULL;
+
+ acpi_get_device_data(handle, &adev, get_acpi_device);
+ return adev;
+}
+
+void acpi_bus_put_acpi_device(struct acpi_device *adev)
+{
+ put_device(&adev->dev);
+}
+
int acpi_device_add(struct acpi_device *device,
void (*release)(struct device *))
{
Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -340,7 +340,7 @@ static void acpi_bus_osc_support(void)
*/
static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device;
struct acpi_driver *driver;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
@@ -387,12 +387,14 @@ static void acpi_bus_notify(acpi_handle
break;
}
- acpi_bus_get_device(handle, &device);
+ device = acpi_bus_get_acpi_device(handle);
if (device) {
driver = device->driver;
if (driver && driver->ops.notify &&
(driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
driver->ops.notify(device, type);
+
+ acpi_bus_put_acpi_device(device);
}
}
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -381,6 +381,8 @@ extern int unregister_acpi_notifier(stru
*/
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
+struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);
+void acpi_bus_put_acpi_device(struct acpi_device *adev);
acpi_status acpi_bus_get_status_handle(acpi_handle handle,
unsigned long long *sta);
int acpi_bus_get_status(struct acpi_device *device);
next prev parent reply other threads:[~2014-02-03 23:37 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 ` [PATCH 4/24][New] ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event() Rafael J. Wysocki
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 ` Rafael J. Wysocki [this message]
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=1957606.iEkqlTBjjf@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).