1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 09:00:12 +00:00

ACPI support fix for 6.19-rc5

Fix the ACPI/PCI legacy interrupts (INTx) parsing in the cases when
 the ACPI Global System Interrupt (GSI) value is a 32-bit one with
 the MSB set that is interpreted as a negative integer and causes
 acpi_pci_link_allocate_irq() to fail and acpi_irq_get_penalty() to
 trigger an out-of-bounds array dereference (Lorenzo Pieralisi)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmlhHEMSHHJqd0Byand5
 c29ja2kubmV0AAoJEO5fvZ0v1OO1sSIIAK1NeCVdGg9YpInOmVSneDENsaWReo9c
 ZxJBKISVPkiwG+8jEbPgIJJcwAXGBgzYBOA/l2S8TkFjj3h6yRidKI2PUabW49KA
 LN0k1Xkts/W4EVvY4d2J5WdNCwzzPi+cxG5fDuL5izZNP4yKJxiOvEybUAmA6i9g
 EqKXnAme/qSGSfZKFltjKDu9OcV+Nq1MSezl5h4JffChIXyJ1vX5tGmM3ENxzwXN
 gBUMk3BKD1TnnmjVO8Cz1WV8oDszOY3Y2+8MBGkbB5P/6Kwkdf2Wh79voddozi3D
 i+kJxdAJBqsUFODprhIYmgYR5duvi8XOj6p94hLzu8yJvvStYcqudRs=
 =v1UK
 -----END PGP SIGNATURE-----

Merge tag 'acpi-6.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI support fix from Rafael Wysocki:
 "This fixes the ACPI/PCI legacy interrupts (INTx) parsing in the case
  when the ACPI Global System Interrupt (GSI) value is a 32-bit one with
  the MSB set.

  That was interpreted as a negative integer and caused
  acpi_pci_link_allocate_irq() to fail and acpi_irq_get_penalty() to
  trigger an out-of-bounds array dereference (Lorenzo Pieralisi)"

* tag 'acpi-6.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI: PCI: IRQ: Fix INTx GSIs signedness
This commit is contained in:
Linus Torvalds 2026-01-09 06:20:15 -10:00
commit 553410fcb9
4 changed files with 44 additions and 29 deletions

View File

@ -188,7 +188,7 @@ static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
* the IRQ value, which is hardwired to specific interrupt inputs on
* the interrupt controller.
*/
pr_debug("%04x:%02x:%02x[%c] -> %s[%d]\n",
pr_debug("%04x:%02x:%02x[%c] -> %s[%u]\n",
entry->id.segment, entry->id.bus, entry->id.device,
pin_name(entry->pin), prt->source, entry->index);
@ -384,7 +384,7 @@ static inline bool acpi_pci_irq_valid(struct pci_dev *dev, u8 pin)
int acpi_pci_irq_enable(struct pci_dev *dev)
{
struct acpi_prt_entry *entry;
int gsi;
u32 gsi;
u8 pin;
int triggering = ACPI_LEVEL_SENSITIVE;
/*
@ -422,18 +422,21 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
return 0;
}
rc = -ENODEV;
if (entry) {
if (entry->link)
gsi = acpi_pci_link_allocate_irq(entry->link,
rc = acpi_pci_link_allocate_irq(entry->link,
entry->index,
&triggering, &polarity,
&link);
else
&link, &gsi);
else {
gsi = entry->index;
} else
gsi = -1;
rc = 0;
}
}
if (gsi < 0) {
if (rc < 0) {
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case.

View File

@ -448,7 +448,7 @@ static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = {
/* >IRQ15 */
};
static int acpi_irq_pci_sharing_penalty(int irq)
static int acpi_irq_pci_sharing_penalty(u32 irq)
{
struct acpi_pci_link *link;
int penalty = 0;
@ -474,7 +474,7 @@ static int acpi_irq_pci_sharing_penalty(int irq)
return penalty;
}
static int acpi_irq_get_penalty(int irq)
static int acpi_irq_get_penalty(u32 irq)
{
int penalty = 0;
@ -528,7 +528,7 @@ static int acpi_irq_balance = -1; /* 0: static, 1: balance */
static int acpi_pci_link_allocate(struct acpi_pci_link *link)
{
acpi_handle handle = link->device->handle;
int irq;
u32 irq;
int i;
if (link->irq.initialized) {
@ -598,44 +598,53 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
return 0;
}
/*
* acpi_pci_link_allocate_irq
* success: return IRQ >= 0
* failure: return -1
/**
* acpi_pci_link_allocate_irq(): Retrieve a link device GSI
*
* @handle: Handle for the link device
* @index: GSI index
* @triggering: pointer to store the GSI trigger
* @polarity: pointer to store GSI polarity
* @name: pointer to store link device name
* @gsi: pointer to store GSI number
*
* Returns:
* 0 on success with @triggering, @polarity, @name, @gsi initialized.
* -ENODEV on failure
*/
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
int *polarity, char **name)
int *polarity, char **name, u32 *gsi)
{
struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_pci_link *link;
if (!device) {
acpi_handle_err(handle, "Invalid link device\n");
return -1;
return -ENODEV;
}
link = acpi_driver_data(device);
if (!link) {
acpi_handle_err(handle, "Invalid link context\n");
return -1;
return -ENODEV;
}
/* TBD: Support multiple index (IRQ) entries per Link Device */
if (index) {
acpi_handle_err(handle, "Invalid index %d\n", index);
return -1;
return -ENODEV;
}
mutex_lock(&acpi_link_lock);
if (acpi_pci_link_allocate(link)) {
mutex_unlock(&acpi_link_lock);
return -1;
return -ENODEV;
}
if (!link->irq.active) {
mutex_unlock(&acpi_link_lock);
acpi_handle_err(handle, "Link active IRQ is 0!\n");
return -1;
return -ENODEV;
}
link->refcnt++;
mutex_unlock(&acpi_link_lock);
@ -647,7 +656,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
if (name)
*name = acpi_device_bid(link->device);
acpi_handle_debug(handle, "Link is referenced\n");
return link->irq.active;
*gsi = link->irq.active;
return 0;
}
/*

View File

@ -89,11 +89,11 @@ int xen_acpi_get_gsi_info(struct pci_dev *dev,
int *trigger_out,
int *polarity_out)
{
int gsi;
u32 gsi;
u8 pin;
struct acpi_prt_entry *entry;
int trigger = ACPI_LEVEL_SENSITIVE;
int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
int ret, polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW;
if (!dev || !gsi_out || !trigger_out || !polarity_out)
@ -105,17 +105,18 @@ int xen_acpi_get_gsi_info(struct pci_dev *dev,
entry = acpi_pci_irq_lookup(dev, pin);
if (entry) {
ret = 0;
if (entry->link)
gsi = acpi_pci_link_allocate_irq(entry->link,
ret = acpi_pci_link_allocate_irq(entry->link,
entry->index,
&trigger, &polarity,
NULL);
NULL, &gsi);
else
gsi = entry->index;
} else
gsi = -1;
ret = -ENODEV;
if (gsi < 0)
if (ret < 0)
return -EINVAL;
*gsi_out = gsi;

View File

@ -51,7 +51,7 @@
int acpi_irq_penalty_init(void);
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
int *polarity, char **name);
int *polarity, char **name, u32 *gsi);
int acpi_pci_link_free_irq(acpi_handle handle);
/* ACPI PCI Device Binding */