Linux PCI subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: linux-pci@vger.kernel.org
Subject: Re: [PATCH v1 1/7] ACPI: scan: Stop calling acpi_bus_init_power() early
Date: Mon, 31 Aug 2026 20:14:26 +0000	[thread overview]
Message-ID: <20260831201426.92F091F000E9@smtp.kernel.org> (raw)
In-Reply-To: <10913616.nUPlyArG6x@rafael.j.wysocki>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Transient failures in early PCI enumeration due to unmet ACPI dependencies permanently disable ACPI power management for the device.
- [High] Concurrent execution of `acpi_device_set_power` and `acpi_bus_attach` leads to power resource reference count leaks.
- [High] Bitfield data race on `struct acpi_device_flags` leading to corrupted device flags.
- [High] Unprivileged sysfs access to a child's power state bypasses the parent's power resource initialization, leading to reference count underflow and permanent power leaks.
--

commit 00db710bd9860a36a16f28aa782d074b11d43aab
Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

ACPI: scan: Stop calling acpi_bus_init_power() early

This commit prevents premature transition into the D0 power state for
devices with missing dependencies by changing when acpi_bus_init_power()
is called. It updates acpi_device_set_power() to initialize power upfront
and adjusts acpi_bus_attach() to use ACPI power state tracking instead of
the initialized flag.

Link: https://lore.kernel.org/linux-acpi/20260820-acpi-power-resource-ref-fix-v2-1-29818173ea13@linux.spacemit.com/ [1]

> diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
> index aa55ecfc2923c..a680e6972a8c2 100644
> --- a/drivers/acpi/device_pm.c
> +++ b/drivers/acpi/device_pm.c

[ ... ]

> @@ -168,6 +168,12 @@ int acpi_device_set_power(struct acpi_device *device, int state)
>  	    || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
>  		return -EINVAL;
>  
> +	if (device->power.state == ACPI_STATE_UNKNOWN &&
> +	    acpi_bus_init_power(device)) {
> +		device->flags.power_manageable = 0;

[Severity: High]
If acpi_bus_init_power() fails transiently here because dependencies are
unmet (for instance, _PSC or _ON evaluations fail during early PCI
discovery), does this permanently disable ACPI power management for the
device? Since the prior restoration logic was removed from
acpi_bus_attach(), it appears there is no mechanism to recover from this
transient failure when dependencies are met later.

[Severity: High]
Because struct acpi_device_flags is a bitfield, does modifying
power_manageable here without mutual exclusion risk a data race? 

If acpi_device_set_power() runs concurrently with async enumeration
(such as acpi_bus_attach() calling acpi_device_set_enumerated()), they
could perform concurrent read-modify-write operations on the bitfield.
This could cause one of the flag updates (like the visited or enumerated
flag) to be silently lost.

> +		return -ENODEV;
> +	}
> +
>  	acpi_handle_debug(device->handle, "Power state change: %s -> %s\n",
>  			  acpi_power_state_string(device->power.state),
>  			  acpi_power_state_string(state));

[ ... ]

> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index f48715ed827c7..1ad8dffc2dafe 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c

[ ... ]

> @@ -2364,16 +2361,13 @@ static int acpi_bus_attach(struct acpi_device *device, void *first_pass)
>  
>  	acpi_ec_register_opregions(device);
>  
> -	if (!device->flags.initialized) {
> -		device->flags.power_manageable =
> -			device->power.states[ACPI_STATE_D0].flags.valid;
> -		if (acpi_bus_init_power(device))
> -			device->flags.power_manageable = 0;
> +	if (device->flags.power_manageable &&
> +	    device->power.state == ACPI_STATE_UNKNOWN &&
> +	    acpi_bus_init_power(device))

[Severity: High]
Is it possible for acpi_bus_attach() (running asynchronously via
acpi_scan_clear_dep_fn()) and acpi_device_set_power() (reachable via
sysfs power/control) to execute concurrently? 

Both paths now perform a lockless check of
device->power.state == ACPI_STATE_UNKNOWN and subsequently call
acpi_bus_init_power(). Could this lead to both threads acquiring power
resource references via acpi_power_on_resources(), keeping the hardware
powered on indefinitely when the second set of references is leaked?

[Severity: High]
Could an unprivileged user reading the real_power_state sysfs attribute
of a child device bypass this parent initialization?

If a sysfs read calls acpi_device_get_power() on the child, it can
locklessly mutate the parent's state to ACPI_STATE_D0:

acpi_device_get_power() {
    ...
    if (!device->power.flags.ignore_parent && parent &&
        parent->power.state == ACPI_STATE_UNKNOWN &&
        result == ACPI_STATE_D0)
            parent->power.state = ACPI_STATE_D0;
    ...
}

If this occurs before acpi_bus_attach() runs for the parent, the
lockless check here in acpi_bus_attach() will see a state other than
ACPI_STATE_UNKNOWN and skip calling acpi_bus_init_power(). 

Does this result in the parent's power resources never being initialized,
leading to a reference count underflow when the device later transitions
to D3?

> +		device->flags.power_manageable = 0;
>  
> -		device->flags.initialized = true;
> -	} else if (device->flags.visited) {
> +	if (device->flags.visited)
>  		goto ok;
> -	}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/3435655.aeNJFYEL58@rafael.j.wysocki?part=1

  reply	other threads:[~2026-08-31 20:14 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 16:20 [PATCH v1 0/7] ACPI: scan: Address power management initialization and PCI devices handling Rafael J. Wysocki
2026-08-31 16:24 ` [PATCH v1 1/7] ACPI: scan: Stop calling acpi_bus_init_power() early Rafael J. Wysocki
2026-08-31 20:14   ` sashiko-bot [this message]
2026-09-01 17:31     ` Rafael J. Wysocki (Intel)
2026-09-01  8:27   ` Andy Shevchenko
2026-08-31 16:25 ` [PATCH v1 2/7] ACPI: PM: Introduce acpi_device_init_power() Rafael J. Wysocki
2026-08-31 20:25   ` sashiko-bot
2026-09-01  8:29   ` Andy Shevchenko
2026-09-01 16:38     ` Rafael J. Wysocki (Intel)
2026-08-31 17:59 ` [PATCH v1 3/7] ACPI: bus: Drop initialized flag from struct acpi_device_flags Rafael J. Wysocki
2026-08-31 21:03   ` sashiko-bot
2026-08-31 17:59 ` [PATCH v1 4/7] ACPI: scan: Combine two conditionals in acpi_bus_attach() Rafael J. Wysocki
2026-08-31 21:05   ` sashiko-bot
2026-09-01  8:40   ` Andy Shevchenko
2026-09-01 19:11     ` Rafael J. Wysocki (Intel)
2026-08-31 17:59 ` [PATCH v1 5/7] ACPI: scan: Add ACPI device "enumerated" marker Rafael J. Wysocki
2026-08-31 21:14   ` sashiko-bot
2026-08-31 17:59 ` [PATCH v1 6/7] ACPI: scan: Adjust and rename acpi_bus_attach() Rafael J. Wysocki
2026-08-31 21:17   ` sashiko-bot
2026-08-31 17:59 ` [PATCH v1 7/7] ACPI: scan: Take PCI device enumeration into account directly Rafael J. Wysocki
2026-08-31 21:23   ` sashiko-bot
2026-09-01  8:44   ` Andy Shevchenko
2026-09-01 19:14     ` Rafael J. Wysocki (Intel)
2026-09-02 12:42 ` [PATCH v1 0/7] ACPI: scan: Address power management initialization and PCI devices handling Peixin Xie

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=20260831201426.92F091F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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