⬢ DragonFlyBSD Kernel Audit
DF-5650 / fix.diff
← back to finding ↓ download raw
--- a/sys/platform/pc64/acpica/acpi_srat.c
+++ b/sys/platform/pc64/acpica/acpi_srat.c
@@ -88,16 +88,37 @@
 		goto done;
 	}
 
+	/*
+	 * Validate every subtable entry before touching any field beyond
+	 * the two-byte ACPI_SUBTABLE_HEADER, mirroring
+	 * madt_iterate_entries() (acpi_madt.c).  The entry Type/Length are
+	 * firmware-supplied: Length == 0 wedges the walk in an infinite
+	 * loop, and an entry extending past the table end makes the parser
+	 * read beyond the mapped table.
+	 */
 	cpu = NULL;
 
 	for (mem = (srat_entry_t *)(srat + 1);
-	     (char *)mem < (char *)srat + srat->Header.Length;
+	     (char *)mem + sizeof(mem->head) <=
+	     (char *)srat + srat->Header.Length;
 	     mem = (srat_entry_t *)((char *)mem + mem->head.Length)) {
+		if (mem->head.Length < sizeof(mem->head) ||
+		    (char *)mem + mem->head.Length >
+		    (char *)srat + srat->Header.Length) {
+			kprintf("srat_probe: invalid SRAT entry len %u\n",
+				mem->head.Length);
+			break;
+		}
 		/*
 		 * Mem scan memory affinity only
 		 */
 		if (mem->head.Type != ACPI_SRAT_TYPE_MEMORY_AFFINITY)
 			continue;
+		if (mem->head.Length < sizeof(mem->mem)) {
+			kprintf("srat_probe: truncated memory affinity "
+				"entry len %u\n", mem->head.Length);
+			continue;
+		}
 		if ((mem->mem.Flags & ACPI_SRAT_MEM_ENABLED) == 0)
 			continue;
 
@@ -111,13 +132,21 @@
 		 */
 		if (cpu == NULL ||
 		    mem->mem.ProximityDomain != cpu->cpu.ProximityDomainLo) {
+			cpu = NULL;
 			for (cpu = (srat_entry_t *)(srat + 1);
-			     (char *)cpu < (char *)srat + srat->Header.Length;
+			     (char *)cpu + sizeof(cpu->head) <=
+			     (char *)srat + srat->Header.Length;
 			     cpu = (srat_entry_t *)((char *)cpu +
 						    cpu->head.Length)) {
+				if (cpu->head.Length < sizeof(cpu->head) ||
+				    (char *)cpu + cpu->head.Length >
+				    (char *)srat + srat->Header.Length)
+					break;
 				if (cpu->head.Type !=
 				    ACPI_SRAT_TYPE_CPU_AFFINITY)
 					continue;
+				if (cpu->head.Length < sizeof(cpu->cpu))
+					break;
 				if ((cpu->cpu.Flags &
 				     ACPI_SRAT_CPU_USE_AFFINITY) == 0)
 					continue;