In June 2024, a security issue was identified and fixed in the Linux kernel’s SPI subsystem: CVE-2024-36930. If you use devices (such as CAN or SPI controllers) on Linux, this bug could potentially crash your system due to a _null pointer dereference_ during SPI message transfers.

In this post, we'll break down what happened, show you the vulnerable and fixed code, explain how it can be exploited (in simple terms), and point you to the official sources.

What is SPI and Why Does This Matter?

The SPI (Serial Peripheral Interface) subsystem allows Linux kernels to talk to all sorts of hardware — sensors, controllers, flash chips, and more. If you have electronics connected over SPI, the driver uses spi_sync() to send messages.

When something’s wrong with the way these messages are managed, it can take down the whole kernel, affecting reliability, uptime, and even security if an attacker can exploit the issue.

The Vulnerability Explained

Short version:
If you called spi_sync() with more than one queued message, and then reused the same message struct, a leftover function pointer (complete) doesn’t get cleared. Under certain conditions, it points to nothing, but the code still tries to _call_ it — leading to a null pointer dereference (a sure-fire kernel crash).

This is simplified kernel-side SPI code highlighting the issue

// (simplified) called after SPI transfer is done
static void spi_finalize_current_message(struct spi_master *master)
{
    struct spi_message *message = master->cur_msg;
    // ... (some logic)
    if (message->complete)   // <-- PROBLEM! pointer might be invalid
        message->complete(message->context);
    // context is cleared, but complete is NOT set to NULL
    message->context = NULL;
    // complete remains != NULL!
}

Real Problem:

The complete callback remains set, even when context is cleared.

- Next time this message is sent (with the same struct), the callback tries to run and can crash the kernel.

When this happens, you may see something like

Kernel panic - not syncing: Fatal exception
Call Trace:
 _raw_spin_lock_irqsave
 complete_with_flags
 spi_complete
 spi_finalize_current_message
 spi_transfer_one_message
 __spi_pump_transfer_message
 __spi_transfer_message_noqueue
 __spi_sync
 spi_sync
 mcp251xfd_regmap_crc_read [mcp251xfd]
 ...

What did developers do?

They made sure to _also_ set message->complete = NULL; once the transfer is done, not just clear the context.

// snippet from the fix (commit)
static void spi_finalize_current_message(struct spi_master *master)
{
    struct spi_message *message = master->cur_msg;
    // ... complete transfer
    if (message->complete)
        message->complete(message->context);
    // Now clear both
    message->context = NULL;
    message->complete = NULL;
}

Reference:
- Upstream commit and discussion
- CVE-2024-36930 at Mitre
- Linux kernel mailing list thread

Can You Trigger This on Purpose?

Yes — if you can write or influence drivers to reuse SPI messages incorrectly (possible in embedded, custom, or buggy third-party drivers), you can force a kernel crash.

Exploit Scenario

1. Write (or compromise) a kernel driver that uses spi_sync() and reuses a message struct without resetting the callback.

If it points to NULL or freed memory, you get a crash or panic (DoS aka Denial of Service).

NOTE:
This isn't a privilege escalation (can't take over the machine), but it _is_ a potential for remote denial-of-service if exposed over a vulnerable SPI-connected network device, e.g., a CAN controller.

This simplified driver code can cause the crash

static struct spi_message msg;

void foo(struct spi_device *spi)
{
    static DECLARE_COMPLETION_ONSTACK(done);
    msg.complete = NULL;  // (should be set to something, then cleared)
    msg.context = &done;

    // Incorrect: reusing 'msg' without proper reset
    spi_sync(spi, &msg);
    // Now, reuse 'msg' (unsafe!)
    spi_sync(spi, &msg);  // Crash!
}

After the first transfer finishes, msg.complete isn't cleared. If the kernel then tries to call it again, it's garbage or NULL.

Upgrade your kernel — All mainstream Linux trees have picked up the fix as of 2024-06-18.

- Check custom SPI drivers — Don't reuse SPI messages unless you reset both context and complete.

Full References

- Upstream kernel fix commit
- CVE-2024-36930 at cve.org
- SPI subsystem docs (kernel.org)
- Discussion thread

TL;DR

CVE-2024-36930 is a Linux kernel bug that could crash systems using SPI devices if a certain message struct is reused without care.
Fix: Upgrade your kernel and be careful with SPI message reuse in drivers.

Timeline

Published on: 05/30/2024 16:15:16 UTC
Last modified on: 06/10/2024 19:20:48 UTC