Subject: kern/34241: ACPI panics instantly - presumably motherboard-specific
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <dave@dtsp.co.nz>
List: netbsd-bugs
Date: 08/20/2006 10:55:01
>Number:         34241
>Category:       kern
>Synopsis:       ACPI panics instantly - presumably motherboard-specific
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Aug 20 10:55:00 +0000 2006
>Originator:     Dave Sainty
>Release:        HEAD @ Sun Aug 20 04:46:24 UTC 2006
>Organization:
Dynamic Technology Services and Products Ltd (NZ)
>Environment:
i386, NetBSD-current
System: NetBSD tequila.dave.dtsp.co.nz 4.99.1 NetBSD 4.99.1 (TEQUILA-$Revision: 1.101 $) #5: Sun Aug 20 20:07:00 NZST 2006 dave@tequila.dave.dtsp.co.nz:/usr/src/NetBSD-tequila-20060817/src/sys/arch/i386/compile/TEQUILA i386
Architecture: i386
Machine: i386

>Description:
	Booting NetBSD-current on a P4C800-E Deluxe with ACPI enabled panics
	immediately.

	The problem appears to be that the ACPI code overran the pages
	assigned for ACPI (by whatever process that happens!).

	The memcpy() that panics is reading from 0xc16d6fc0.  The Length field
	value is 24, but sizeof(ACPI_RESOURCE) is 66.  Presumably 0xc16d7000
	isn't mapped.

>How-To-Repeat:
	Boot NetBSD-current on a P4C800-E Deluxe with ACPI enabled.

>Fix:

--- src/sys/dev/acpi/acpi_pci_link.c.orig	2006-07-10 21:18:36.000000000 +1200
+++ src/sys/dev/acpi/acpi_pci_link.c	2006-08-20 20:00:09.000000000 +1200
@@ -298,10 +298,25 @@
 		req->res_index++;
 
 		/*
-		 * Stash a copy of the resource for later use when doing
-		 * _SRS.
+		 * Stash a copy of the resource for later use when
+		 * doing _SRS.
+		 *
+		 * Note that in theory res->Length may exceed the size
+		 * of ACPI_RESOURCE, due to variable length lists in
+		 * subtypes.  However, all uses of l_prs_template only
+		 * rely on lists lengths of zero or one, for which
+		 * sizeof(ACPI_RESOURCE) is sufficient space anyway.
+		 * We cannot read longer than Length bytes, in case we
+		 * read off the end of mapped memory.  So we read
+		 * whichever length is shortest, Length or
+		 * sizeof(ACPI_RESOURCE).
 		 */
-		memcpy(&link->l_prs_template, res, sizeof(ACPI_RESOURCE));
+		KASSERT(res->Length >= ACPI_RS_SIZE_MIN);
+
+		memset(&link->l_prs_template, 0, sizeof(link->l_prs_template));
+		memcpy(&link->l_prs_template, res,
+		       MIN(res->Length, sizeof(link->l_prs_template)));
+
 		if (is_ext_irq) {
 			link->l_num_irqs =
 			    res->Data.ExtendedIrq.InterruptCount;