summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-11-30 06:55:43 +0000
committernjl <njl@FreeBSD.org>2004-11-30 06:55:43 +0000
commit504bb0d4c899c5de8eb35b1d57ebd6411f1fed30 (patch)
tree4ae5e1faa4b4c4b3334e55b1e3f0c5e6fa942eca /sys/dev
parent7822d39332bec2bbf561a95f0cbc70fe67ca6a05 (diff)
downloadFreeBSD-src-504bb0d4c899c5de8eb35b1d57ebd6411f1fed30.zip
FreeBSD-src-504bb0d4c899c5de8eb35b1d57ebd6411f1fed30.tar.gz
Make sure the link array is big enough to hold both _CRS and _PRS
resource lists. It used to be sized based only on _CRS, hence _PRS could perform an out-of-bounds access if it was larger (i.e., when there are dependent functions). Add asserts to detect this case. Note, this is only a temporary fix and I believe _PRS and _CRS should have separate arrays. Also, fix a typo where the wrong irq was being check for the APIC case. Submitted by: tegge
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpica/acpi_pci_link.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c
index c79cc04..e6675f1 100644
--- a/sys/dev/acpica/acpi_pci_link.c
+++ b/sys/dev/acpica/acpi_pci_link.c
@@ -131,12 +131,16 @@ acpi_pci_link_probe(device_t dev)
}
static ACPI_STATUS
-acpi_count_resources(ACPI_RESOURCE *res, void *context)
+acpi_count_irq_resources(ACPI_RESOURCE *res, void *context)
{
int *count;
count = (int *)context;
- (*count)++;
+ switch (res->Id) {
+ case ACPI_RSTYPE_IRQ:
+ case ACPI_RSTYPE_EXT_IRQ:
+ (*count)++;
+ }
return (AE_OK);
}
@@ -148,11 +152,13 @@ link_add_crs(ACPI_RESOURCE *res, void *context)
ACPI_SERIAL_ASSERT(pci_link);
req = (struct link_res_request *)context;
- link = &req->sc->pl_links[req->count];
- req->count++;
switch (res->Id) {
case ACPI_RSTYPE_IRQ:
case ACPI_RSTYPE_EXT_IRQ:
+ KASSERT(req->count < req->sc->pl_num_links,
+ ("link_add_crs: array boundary violation"));
+ link = &req->sc->pl_links[req->count];
+ req->count++;
if (res->Id == ACPI_RSTYPE_IRQ) {
if (res->Data.Irq.NumberOfInterrupts > 0) {
KASSERT(res->Data.Irq.NumberOfInterrupts == 1,
@@ -188,11 +194,13 @@ link_add_prs(ACPI_RESOURCE *res, void *context)
ACPI_SERIAL_ASSERT(pci_link);
req = (struct link_res_request *)context;
- link = &req->sc->pl_links[req->count];
- req->count++;
switch (res->Id) {
case ACPI_RSTYPE_IRQ:
case ACPI_RSTYPE_EXT_IRQ:
+ KASSERT(req->count < req->sc->pl_num_links,
+ ("link_add_prs: array boundary violation"));
+ link = &req->sc->pl_links[req->count];
+ req->count++;
/*
* Stash a copy of the resource for later use when doing
@@ -220,7 +228,7 @@ link_add_prs(ACPI_RESOURCE *res, void *context)
M_PCI_LINK, M_WAITOK | M_ZERO);
for (i = 0; i < link->l_num_irqs; i++) {
link->l_irqs[i] = irqs[i];
- if (irqs[1] >= NUM_ISA_INTERRUPTS)
+ if (irqs[i] >= NUM_ISA_INTERRUPTS)
link->l_isa_irq = 0;
}
break;
@@ -283,6 +291,7 @@ acpi_pci_link_attach(device_t dev)
struct link_res_request req;
ACPI_STATUS status;
int i;
+ int prslinks;
sc = device_get_softc(dev);
ACPI_SERIAL_BEGIN(pci_link);
@@ -292,11 +301,24 @@ acpi_pci_link_attach(device_t dev)
* a link array to allocate.
*/
status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
- acpi_count_resources, &sc->pl_num_links);
+ acpi_count_irq_resources, &sc->pl_num_links);
if (ACPI_FAILURE(status))
return (ENXIO);
if (sc->pl_num_links == 0)
return (0);
+
+ /*
+ * Try to make the number of resources sufficiently large
+ * for traversal of both _PRS and _CRS.
+ *
+ * XXX Temporary fix for out-of-bounds access in prs_add_links().
+ * We really need to handle these in separate arrays. -- njl
+ */
+ prslinks = 0;
+ status = AcpiWalkResources(acpi_get_handle(dev), "_PRS",
+ acpi_count_irq_resources, &prslinks);
+ if (prslinks > sc->pl_num_links)
+ sc->pl_num_links = prslinks;
sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links,
M_PCI_LINK, M_WAITOK | M_ZERO);
OpenPOWER on IntegriCloud