]> www.infradead.org Git - users/hch/misc.git/commitdiff
ACPI: GTDT: Relax sanity checking on Platform Timers array count
authorOliver Upton <oliver.upton@linux.dev>
Tue, 28 Jan 2025 00:17:49 +0000 (00:17 +0000)
committerWill Deacon <will@kernel.org>
Thu, 13 Feb 2025 11:12:47 +0000 (11:12 +0000)
Perhaps unsurprisingly there are some platforms where the GTDT isn't
quite right and the Platforms Timer array overflows the length of the
overall table.

While the recently-added sanity checking isn't wrong, it makes it
impossible to boot the kernel on offending platforms. Try to hobble
along and limit the Platform Timer count to the bounds of the table.

Cc: Marc Zyngier <maz@kernel.org>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Zheng Zengkai <zhengzengkai@huawei.com>
Cc: stable@vger.kernel.org
Fixes: 263e22d6bd1f ("ACPI: GTDT: Tighten the check for the array of platform timer structures")
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Acked-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Link: https://lore.kernel.org/r/20250128001749.3132656-1-oliver.upton@linux.dev
Signed-off-by: Will Deacon <will@kernel.org>
drivers/acpi/arm64/gtdt.c

index 3561553eff8b5e4a06ef232db1123e8a1f6c44f2..70f8290b659de58f7d4b018401465e3ef634dfe8 100644 (file)
@@ -163,7 +163,7 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
 {
        void *platform_timer;
        struct acpi_table_gtdt *gtdt;
-       int cnt = 0;
+       u32 cnt = 0;
 
        gtdt = container_of(table, struct acpi_table_gtdt, header);
        acpi_gtdt_desc.gtdt = gtdt;
@@ -188,13 +188,17 @@ int __init acpi_gtdt_init(struct acpi_table_header *table,
                cnt++;
 
        if (cnt != gtdt->platform_timer_count) {
+               cnt = min(cnt, gtdt->platform_timer_count);
+               pr_err(FW_BUG "limiting Platform Timer count to %d\n", cnt);
+       }
+
+       if (!cnt) {
                acpi_gtdt_desc.platform_timer = NULL;
-               pr_err(FW_BUG "invalid timer data.\n");
-               return -EINVAL;
+               return 0;
        }
 
        if (platform_timer_count)
-               *platform_timer_count = gtdt->platform_timer_count;
+               *platform_timer_count = cnt;
 
        return 0;
 }