PCI/ACPI: Validate acpi_pci_set_power_state() parameter
commit 5557b62634abbd55bab7b154ce4bca348ad7f96f upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a905b0b318
commit
788c76c33d
@ -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 (!error)
|
||||
pci_dbg(dev, "power state changed by ACPI to %s\n",
|
||||
acpi_power_state_string(adev->power.state));
|
||||
if (state == PCI_D3cold) {
|
||||
if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
|
||||
PM_QOS_FLAGS_ALL)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return error;
|
||||
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 0;
|
||||
}
|
||||
|
||||
pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
|
||||
|
Loading…
Reference in New Issue
Block a user