CVE-2021-46953 - Linux Kernel ACPI GTDT Bug Explained & How It Was Fixed

!Linux Kernel Vulnerability

Introduction

In early 2021, a subtle but potentially serious vulnerability was patched in the Linux kernel’s ARM architecture codebase. Named CVE-2021-46953, this bug came from faulty error handling in the ACPI GTDT (Generic Timer Description Table) driver, uncovered after kernel developers noticed system instability on certain ARM platforms.

And how you can spot it in code.

All with straightforward language and practical examples.

What Is CVE-2021-46953?

CVE-2021-46953 is a vulnerability in the Linux kernel’s ARM ACPI GTDT driver (a component that helps the kernel understand timers and interrupts described by firmware during boot).

Here’s what went wrong

- When the driver tried to set up interrupts as described by the machine’s firmware, it didn't actually check if the interrupt mapping succeeded.
- If an error occurred (for example, if the firmware supplied a bogus or *illegal* interrupt number), the driver would attempt to “unmap” that interrupt—regardless of whether it had ever succeeded in mapping it.
- On some ARM systems, if the bogus interrupt number overlapped with the reserved range used for *inter-processor interrupts* (IPIs, used for CPU communication), the unmapping could affect those IPIs.
- Suddenly, CPUs could lose their ability to signal each other, leading to system crashes or unpredictable behavior.

Who Discovered It?

Linux kernel developer Dann Frazier first reported the issue after experiencing “fireworks” (kernel crashes and instability) due to this hole.

Original Linux Kernel Mailing List thread

- ACPI: GTDT: Don't corrupt interrupt mappings on watchdog probe failure

How Did The Vulnerability Work?

Let’s walk through a simplified version of the error.

When initializing hardware described by firmware, the kernel would

1. Map Interupts: Assign a hardware interrupt number (say, irq_num) described by ACPI/firmware for use.

If Initialization Fails: Unmap the interrupt so no resources are leaked.

The logic sounds good, but here's the problem:
If step 1 never actually succeeded (because irq_num was bogus or unavailable), the code would *still* try to unmap it in step 2.

This might accidentally “unplug” real, in-use IRQs. Especially dangerous if the bogus irq_num pointed at an IPI number.

Below is a simplified version of what the buggy code did

int irq_num = acpi_get_irq(...);

if (irq_num < ) {
    // Failed to get interrupt - *should not try to unmap!*
    goto error;
}

// ...Do other work...

error:
    // Unmap the IRQ -- even if it was never mapped
    irq_dispose_mapping(irq_num);
    return -ENODEV;

If acpi_get_irq() failed (irq_num < ), irq_num might be -1, or an invalid number, or even an IPI. The code would then attempt to unmap it, causing problems.

Realistically, this isn’t a direct “remote exploit” bug.

- However, *malicious firmware* (or a misconfigured ACPI table) could assign out-of-range or reserved IRQ numbers.
- If the kernel is run on such a platform, the driver could unmap critical IPIs, destabilizing or crashing the system shortly after boot.

Risk

- More likely to be triggered by a manufacturer’s ACPI/firmware bug than a remote attack.
- Could be used in a *denial-of-service* scenario by someone who can alter firmware or inject bad ACPI tables.

The Fix: How Developers Resolved It

Main idea:
*Only* unmap the interrupt if it was actually mapped successfully.

Fixed Code Example

int irq_num = acpi_get_irq(...);

if (irq_num <= ) {
    // Only free if we have a valid mapping!
    return -ENODEV;
}

// ...Do other work...

cleanup:
    irq_dispose_mapping(irq_num); // Now only ever called if irq_num is valid
    return -ENODEV;

Or, in the real kernel commit

- irq_dispose_mapping(irq);
+ if (irq > )
+     irq_dispose_mapping(irq);

Reference to actual commit:
Git commit: ACPI: GTDT: Don’t corrupt interrupt mappings on watchdog probe failure

Summary of Solution

> The kernel now double-checks if an interrupt number is valid and not in a protected or error range before unmapping it. This “saner behaviour” prevents accidental unmapping of important (and unrelated) interrupts.

What To Do If You’re Affected

- Most users: Upgrade to a Linux kernel version after March 2021. All major distributions have applied this fix.
- Kernel hackers/system integrators: Check if your custom kernels or platforms have the patch.
- Developers of firmware: Double-check that your ACPI/GTDT tables don't request interrupts in the SGI/IPI range.

References

- Linux Kernel Commit (mainline)
- Linux-acpi Mailing List Discussion
- NVD CVE-2021-46953 Record

Conclusion: Why This Matters

CVE-2021-46953 is a great example of how a “small” bug in error-handling logic can have big consequences—especially in core system code like the Linux kernel. While direct attacks may be rare, such bugs can be devastating on systems with bad firmware or for those assembling custom kernels and hardware.

The fix is simple, but the lesson is important: always check if your operations succeeded before cleaning up. Overzealous error handling can be as dangerous as too little!


If you found this post helpful, consider sharing it with other system developers and kernel enthusiasts!

Timeline

Published on: 02/27/2024 19:04:06 UTC
Last modified on: 04/10/2024 20:15:31 UTC