summaryrefslogtreecommitdiff
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2023-06-21 16:36:12 -0500
committerBjorn Helgaas <bhelgaas@google.com>2023-06-23 12:28:01 -0500
commit5557b62634abbd55bab7b154ce4bca348ad7f96f (patch)
tree238b913ad2be04a824d3cf9ce19541d74c90f30f /drivers/pci/pci-acpi.c
parent9e30fd26f43b89cb6b4e850a86caa2e50dedb454 (diff)
PCI/ACPI: Validate acpi_pci_set_power_state() parameter
Previously acpi_pci_set_power_state() assumed the requested power state was valid (PCI_D0 ... PCI_D3cold). If a caller supplied something else, we could index outside the state_conv[] array and pass junk to acpi_device_set_power(). Validate the pci_power_t parameter and return -EINVAL if it's invalid. Link: https://lore.kernel.org/r/20230621222857.GA122930@bhelgaas Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 052a611081ec..bf545f719182 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1053,32 +1053,37 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
[PCI_D3hot] = ACPI_STATE_D3_HOT,
[PCI_D3cold] = ACPI_STATE_D3_COLD,
};
- int error = -EINVAL;
+ int error;
/* If the ACPI device has _EJ0, ignore the device */
if (!adev || acpi_has_method(adev->handle, "_EJ0"))
return -ENODEV;
switch (state) {
- case PCI_D3cold:
- if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
- PM_QOS_FLAGS_ALL) {
- error = -EBUSY;
- break;
- }
- fallthrough;
case PCI_D0:
case PCI_D1:
case PCI_D2:
case PCI_D3hot:
- error = acpi_device_set_power(adev, state_conv[state]);
+ case PCI_D3cold:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (state == PCI_D3cold) {
+ if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
+ PM_QOS_FLAGS_ALL)
+ return -EBUSY;
}
- if (!error)
- pci_dbg(dev, "power state changed by ACPI to %s\n",
- acpi_power_state_string(adev->power.state));
+ error = acpi_device_set_power(adev, state_conv[state]);
+ if (error)
+ return error;
+
+ pci_dbg(dev, "power state changed by ACPI to %s\n",
+ acpi_power_state_string(adev->power.state));
- return error;
+ return 0;
}
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)