:: commit 947a9b2c3a51983fb8671c516dddaf7f7b9f848a

Mintsuki <mintsuki@protonmail.com> — 2026-04-01 20:41

parents: bb4f6c4c9f

sys/lapic, sys/smp: Validate MADT entry length against table boundary

diff --git a/common/sys/lapic.c b/common/sys/lapic.c
index 08d40fd3..8f6d055a 100644
--- a/common/sys/lapic.c
+++ b/common/sys/lapic.c
@@ -51,7 +51,8 @@ void lapic_prep_lint(struct madt *madt, uint32_t acpi_uid, bool x2apic) {
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0) {
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -227,7 +228,8 @@ void lapic_configure_bsp(void) {
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0) {
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -428,7 +430,8 @@ void init_io_apics(void) {
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0) {
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -447,7 +450,8 @@ void init_io_apics(void) {
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0) {
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
diff --git a/common/sys/smp.c b/common/sys/smp.c
index 7db57b45..2e6724d0 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -168,8 +168,9 @@ struct limine_mp_info *init_smp(size_t   *cpu_count,
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        // Prevent infinite loop on zero-length MADT entry
-        if (*(madt_ptr + 1) == 0) {
+        // Skip zero-length or out-of-bounds MADT entries
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -218,8 +219,9 @@ struct limine_mp_info *init_smp(size_t   *cpu_count,
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        // Prevent infinite loop on zero-length MADT entry
-        if (*(madt_ptr + 1) == 0) {
+        // Skip zero-length or out-of-bounds MADT entries
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -512,7 +514,8 @@ static struct limine_mp_info *try_acpi_smp(size_t   *cpu_count,
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0) {
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -539,7 +542,8 @@ static struct limine_mp_info *try_acpi_smp(size_t   *cpu_count,
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
       (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
       madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0) {
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length) {
             break;
         }
         switch (*madt_ptr) {
@@ -997,7 +1001,8 @@ static struct limine_mp_info *try_acpi_smp(size_t *cpu_count, uint32_t *bsp_phys
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
          (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
          madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0)
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length)
             break;
 
         if (*madt_ptr != MADT_ENTRY_CORE_PIC)
@@ -1020,7 +1025,8 @@ static struct limine_mp_info *try_acpi_smp(size_t *cpu_count, uint32_t *bsp_phys
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
          (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length;
          madt_ptr += *(madt_ptr + 1)) {
-        if (*(madt_ptr + 1) == 0)
+        if (*(madt_ptr + 1) == 0
+         || (uintptr_t)madt_ptr + *(madt_ptr + 1) > (uintptr_t)madt + madt->header.length)
             break;
 
         if (*madt_ptr != MADT_ENTRY_CORE_PIC)
tab: 248 wrap: offon