⬢ DragonFlyBSD Kernel Audit
DF-5583 / fix.diff
← back to finding ↓ download raw
--- sys/platform/pc64/acpica/acpi_fadt.c
+++ sys/platform/pc64/acpica/acpi_fadt.c
@@ -198,12 +198,26 @@ acpi_sci_test(const struct acpi_sci_mode *mode)
 	last_cnt = get_interrupt_counter(acpi_sci_irq, 0);
 
 	machintr_legacy_intr_config(acpi_sci_irq,
 	    mode->sci_trig, mode->sci_pola);
 
+	/*
+	 * NOTE: register_int() returns NULL without panicing if the
+	 * interrupt is already exclusively owned by another handler
+	 * (e.g. a FADT whose SciInterrupt names the 8254 "clk" irq,
+	 * which is registered INTR_EXCL|INTR_CLOCK long before acpi0
+	 * attaches).  In that case never unregister the NULL descriptor,
+	 * leave the line's trigger mode alone, and disable the SCI.
+	 */
 	sci_desc = register_int(acpi_sci_irq,
 	    acpi_sci_dummy_intr, NULL, "sci", NULL,
 	    INTR_EXCL | INTR_CLOCK |
 	    INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0);
+	if (sci_desc == NULL) {
+		kprintf("ACPI FADT: SCI irq %d is not available, disable\n",
+		    acpi_sci_irq);
+		acpi_sci_irq = -1;
+		return TRUE;
+	}
 
 	DELAY(100 * 1000);
 
 	unregister_int(sci_desc, 0);
--- sys/kern/kern_intr.c
+++ sys/kern/kern_intr.c
@@ -420,6 +420,10 @@ unregister_int(void *id, int cpuid)
 
     KKASSERT(cpuid >= 0 && cpuid < ncpus);
 
+    if (id == NULL)		/* defense in depth: register_int() may
+				 * legally fail and return NULL */
+	return;
+
     intr = ((intrec_t)id)->intr;
 
     if (intr < 0 || intr >= MAX_INTS)