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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®