lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <12062887.O9o76ZdvQC@kreacher>
Date:   Mon, 29 Aug 2022 17:21:43 +0200
From:   "Rafael J. Wysocki" <rjw@...ysocki.net>
To:     Linux ACPI <linux-acpi@...r.kernel.org>
Cc:     LKML <linux-kernel@...r.kernel.org>,
        Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
        Linux PM <linux-pm@...r.kernel.org>,
        Dan Carpenter <dan.carpenter@...cle.com>
Subject: [PATCH v1] ACPI: PM: Fix NULL argument handling in acpi_device_get/set_power()

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

In principle, it should be valid to pass NULL as the ACPI device
pointer to acpi_device_get_power() and acpi_device_set_power() and they
both are expected to return -EINVAL in that case, but that has been
broken recently by commit 62fcb99bdf10 ("ACPI: Drop parent field from
struct acpi_device") which has caused the ACPI device pointer to be
dereferenced in these functions before the NULL check.

Fix that and while at it make acpi_device_set_power() only use the
parent field if the target ACPI device object's ignore_parent flag
in not set.

Fixes: 62fcb99bdf10 ("ACPI: Drop parent field from struct acpi_device")
Reported-by: Dan Carpenter <dan.carpenter@...cle.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@...el.com>
---

linux-next material.

---
 drivers/acpi/device_pm.c |   23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

Index: linux-pm/drivers/acpi/device_pm.c
===================================================================
--- linux-pm.orig/drivers/acpi/device_pm.c
+++ linux-pm/drivers/acpi/device_pm.c
@@ -74,13 +74,15 @@ static int acpi_dev_pm_explicit_get(stru
  */
 int acpi_device_get_power(struct acpi_device *device, int *state)
 {
-	struct acpi_device *parent = acpi_dev_parent(device);
 	int result = ACPI_STATE_UNKNOWN;
+	struct acpi_device *parent;
 	int error;
 
 	if (!device || !state)
 		return -EINVAL;
 
+	parent = acpi_dev_parent(device);
+
 	if (!device->flags.power_manageable) {
 		/* TBD: Non-recursive algorithm for walking up hierarchy. */
 		*state = parent ? parent->power.state : ACPI_STATE_D0;
@@ -159,7 +161,6 @@ static int acpi_dev_pm_explicit_set(stru
  */
 int acpi_device_set_power(struct acpi_device *device, int state)
 {
-	struct acpi_device *parent = acpi_dev_parent(device);
 	int target_state = state;
 	int result = 0;
 
@@ -192,13 +193,17 @@ int acpi_device_set_power(struct acpi_de
 		return -ENODEV;
 	}
 
-	if (!device->power.flags.ignore_parent && parent &&
-	    state < parent->power.state) {
-		acpi_handle_debug(device->handle,
-				  "Cannot transition to %s for parent in %s\n",
-				  acpi_power_state_string(state),
-				  acpi_power_state_string(parent->power.state));
-		return -ENODEV;
+	if (!device->power.flags.ignore_parent) {
+		struct acpi_device *parent;
+
+		parent = acpi_dev_parent(device);
+		if (parent && state < parent->power.state) {
+			acpi_handle_debug(device->handle,
+					  "Cannot transition to %s for parent in %s\n",
+					  acpi_power_state_string(state),
+					  acpi_power_state_string(parent->power.state));
+			return -ENODEV;
+		}
 	}
 
 	/*



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ