Skip to content

Commit 5557b62

Browse files
committed
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 <[email protected]> Reviewed-by: Mario Limonciello <[email protected]>
1 parent 9e30fd2 commit 5557b62

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

drivers/pci/pci-acpi.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,32 +1053,37 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
10531053
[PCI_D3hot] = ACPI_STATE_D3_HOT,
10541054
[PCI_D3cold] = ACPI_STATE_D3_COLD,
10551055
};
1056-
int error = -EINVAL;
1056+
int error;
10571057

10581058
/* If the ACPI device has _EJ0, ignore the device */
10591059
if (!adev || acpi_has_method(adev->handle, "_EJ0"))
10601060
return -ENODEV;
10611061

10621062
switch (state) {
1063-
case PCI_D3cold:
1064-
if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
1065-
PM_QOS_FLAGS_ALL) {
1066-
error = -EBUSY;
1067-
break;
1068-
}
1069-
fallthrough;
10701063
case PCI_D0:
10711064
case PCI_D1:
10721065
case PCI_D2:
10731066
case PCI_D3hot:
1074-
error = acpi_device_set_power(adev, state_conv[state]);
1067+
case PCI_D3cold:
1068+
break;
1069+
default:
1070+
return -EINVAL;
1071+
}
1072+
1073+
if (state == PCI_D3cold) {
1074+
if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
1075+
PM_QOS_FLAGS_ALL)
1076+
return -EBUSY;
10751077
}
10761078

1077-
if (!error)
1078-
pci_dbg(dev, "power state changed by ACPI to %s\n",
1079-
acpi_power_state_string(adev->power.state));
1079+
error = acpi_device_set_power(adev, state_conv[state]);
1080+
if (error)
1081+
return error;
1082+
1083+
pci_dbg(dev, "power state changed by ACPI to %s\n",
1084+
acpi_power_state_string(adev->power.state));
10801085

1081-
return error;
1086+
return 0;
10821087
}
10831088

10841089
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)

0 commit comments

Comments
 (0)