From: "Rafael J. Wysocki" <rafael@kernel.org>
To: Linux ACPI <linux-acpi@vger.kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Subject: [PATCH v1 1/4] ACPI: glue: Carry out companion lookup under bus_type_sem
Date: Thu, 10 Sep 2026 19:56:04 +0200 [thread overview]
Message-ID: <3089807.e9J7NaK4W3@rafael.j.wysocki> (raw)
In-Reply-To: <12995802.O9o76ZdvQC@rafael.j.wysocki>
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
When acpi_device_notify() looks up an ACPI companion for the given
device, it invokes callbacks from struct acpi_bus_type() without
synchronization which may lead to a use-after-free if the driver
module containing those callbacks is unloaded at the same time.
Address this by holding bus_type_sem throughout the entire ACPI
companion lookup and the execution of the .setup() callback in
struct acpi_bus_type (if present) instead of dropping the semaphore
(prematurely) after finding a matching struct acpi_bus_type.
For this purpose, rename acpi_get_bus_type() to acpi_companion_lookup(),
make it return a struct acpi_device pointer, and move the relevant code
from acpi_device_notify() to it.
Also notice that the only case in which the .bind() callback from an
ACPI scan handler may need to be invoked is when the given device is
a platform one, so adjust acpi_device_notify() accordingly and drop
the "done" label that is not used any more from it.
Fixes: 2ef5236660b6 ("ACPI: glue: Look for ACPI bus type only if ACPI companion is not known")
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
Applies on top of
https://lore.kernel.org/linux-acpi/12989369.O9o76ZdvQC@rafael.j.wysocki/
which is in linux-pm.git/linux-next now.
Thanks!
---
drivers/acpi/glue.c | 61 +++++++++++++++++++++------------------------
1 file changed, 29 insertions(+), 32 deletions(-)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index a47cccc4efd3..40e6513a9942 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -59,19 +59,34 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
}
EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
-static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
+static struct acpi_device *acpi_companion_lookup(struct device *dev)
{
- struct acpi_bus_type *tmp, *ret = NULL;
+ struct acpi_bus_type *type;
- down_read(&bus_type_sem);
- list_for_each_entry(tmp, &bus_type_list, list) {
- if (tmp->match(dev)) {
- ret = tmp;
- break;
+ guard(rwsem_read)(&bus_type_sem);
+
+ list_for_each_entry(type, &bus_type_list, list) {
+ struct acpi_device *adev;
+
+ if (!type->match(dev))
+ continue;
+
+ adev = type->find_companion(dev);
+ if (!adev) {
+ dev_dbg(dev, "ACPI companion not found\n");
+ return NULL;
}
+ if (acpi_bind_one(dev, adev)) {
+ dev_dbg(dev, "Binding to ACPI companion failed\n");
+ return NULL;
+ }
+ if (type->setup)
+ type->setup(dev);
+
+ return adev;
}
- up_read(&bus_type_sem);
- return ret;
+
+ return NULL;
}
#define FIND_CHILD_MIN_SCORE 1
@@ -360,40 +375,22 @@ void acpi_device_notify(struct device *dev)
ret = acpi_bind_one(dev, NULL);
if (ret) {
- struct acpi_bus_type *type = acpi_get_bus_type(dev);
-
- if (!type)
+ adev = acpi_companion_lookup(dev);
+ if (!adev)
return;
-
- adev = type->find_companion(dev);
- if (!adev) {
- dev_dbg(dev, "ACPI companion not found\n");
- return;
- }
- ret = acpi_bind_one(dev, adev);
- if (ret) {
- dev_dbg(dev, "Binding to ACPI companion failed\n");
- return;
- }
- if (type->setup) {
- type->setup(dev);
- goto done;
- }
} else {
adev = ACPI_COMPANION(dev);
if (dev_is_pci(dev)) {
pci_acpi_setup(dev, adev);
- goto done;
} else if (dev_is_platform(dev)) {
acpi_configure_pmsi_domain(dev);
+
+ if (adev->handler && adev->handler->bind)
+ adev->handler->bind(dev);
}
}
- if (adev->handler && adev->handler->bind)
- adev->handler->bind(dev);
-
-done:
dev_dbg(dev, "Bound to ACPI device %s\n", acpi_dev_name(adev));
}
--
2.51.0
next prev parent reply other threads:[~2026-09-10 17:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 17:51 [PATCH v1 0/4] ACPI: glue: Three fixes and optimization Rafael J. Wysocki
2026-09-10 17:56 ` Rafael J. Wysocki [this message]
2026-09-10 17:56 ` [PATCH v1 2/4] ACPI: glue: Rearrange acpi_bind_one() to avoid breakage Rafael J. Wysocki
2026-09-11 7:40 ` Andy Shevchenko
2026-09-11 10:24 ` Rafael J. Wysocki (Intel)
2026-09-11 16:01 ` Andy Shevchenko
2026-09-10 17:56 ` [PATCH v1 3/4] ACPI: glue: Fix up and adjust acpi_unbind_one() Rafael J. Wysocki
2026-09-10 17:56 ` [PATCH v1 4/4] ACPI: glue: Skip devices with no type in acpi_device_notify() 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=3089807.e9J7NaK4W3@rafael.j.wysocki \
--to=rafael@kernel.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.