A critical race condition bug, now identified as CVE-2024-26607, was found and patched in the Linux kernel’s DRM subsystem, specifically affecting the sii902x HDMI bridge driver. This bug has caused rare kernel panics (crashes) on some Texas Instruments (TI) platform setups, and it could potentially allow Denial of Service (DoS) if exploited at the wrong time. In this article, we break down what went wrong, how the exploit works, and how developers fixed it in easy-to-understand terms.

What is the sii902x?

The sii902x is a Silicon Image HDMI transmitter chip often used as a "bridge" between display controllers (like the DRM subsystem in Linux) and HDMI-connected devices. The Linux kernel has a driver for this chip that helps set up your HDMI display when you boot up or plug it in.

The kernel crash trace looks like this (trimmed for clarity)

[   53.271356]  sii902x_get_edid+x34/x70 [sii902x]
[   53.276066]  sii902x_bridge_get_edid+x14/x20 [sii902x]
...
[   53.336881]  tidss_probe+x128/x264 [tidss]
...

In Simple Terms

- The TI display subsystem (tidss) tries to start ("probes") but waits because the HDMI bridge isn’t ready yet.
- The sii902x probe function is called. It tells the DRM system “I’m ready” by calling drm_bridge_add(), but it hasn’t set up all the parts yet (notably, the I2C interface used to talk to the HDMI transmitter).
- Registering the audio platform device (platform_device_register_data()) triggers the kernel to retry ("probe") the devices that were waiting (deferred).
- Now, tidss starts for real, and eventually calls sii902x_bridge_get_edid() to fetch monitor info.
- This function tries to use the I2C bus – but since I2C setup isn’t done yet, the function gets a null pointer and the kernel crashes.

The Chain in Pseudo-Code

// This is a simplified version for illustration:
struct sii902x_data {
    struct i2c_client *i2c; // <- Should be set before use
    // ...other fields...
};

static struct edid *sii902x_bridge_get_edid(struct drm_bridge *bridge,
                                            struct drm_connector *connector)
{
    struct sii902x_data *sii902x = bridge_to_sii902x(bridge);
    // Tries to use sii902x->i2c, but it's NULL if not initialized yet!
    return sii902x_get_edid(sii902x, connector);
}

Boom! sii902x->i2c is NULL, and any attempt to use it causes a kernel panic.

Exploiting the Vulnerability

While this isn’t a remote code execution bug, it’s very easy, as a user with physical access (or perhaps a malicious kernel module) to trigger this bug, causing the kernel to crash. An attacker could exploit the race by repeatedly adding/removing the HDMI device or manipulating device registration order, causing denial-of-service (DoS):

Example Exploit Scenario

1. Attach an HDMI monitor and repeatedly power cycle it during bootup or insert/remove the device node.

This creates race conditions between device probing and initialization of subcomponents.

3. The unlucky timing allows a deferred device probe to happen _before_ sii902x finished initializing I2C –> null pointer dereference and system crash.

Here is a hypothetical "race trigger" module for demonstration only (do NOT run this on production!)

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>

static int __init trigger_race_init(void)
{
    // This simulates rapid plug/unplug events, causing probe races.
    int i;
    for (i = ; i < 20; ++i) {
        // Remove/add platform device, e.g., HDMI
        // (must match your platform's device names)
        system("echo -n 1 > /sys/bus/platform/devices/some_hdmi/remove");
        msleep(50);
        system("echo -n 1 > /sys/bus/platform/devices/some_hdmi/add");
        msleep(50);
    }
    return ;
}
module_init(trigger_race_init);
MODULE_LICENSE("GPL");

The Fix: Move Initialization to the End

The maintainers fixed this by moving the drm_bridge_add() call to the end of the initialization sequence, after the I2C part is properly set up. This makes sure that if anything starts to probe or query the HDMI bridge, all its fields are ready and not null.

Example Fix (from upstream patch)

static int sii902x_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct sii902x_data *sii902x;
    int ret;

    // ...[1. set up i2c, audio, etc.]...

    // [2. Register audio device, now safe]
    ret = platform_device_register_data(...);

    // [3. NOW register with DRM - all fields ready!]
    drm_bridge_add(&sii902x->bridge);

    // done!
}

Key point:
Nothing can access the bridge until *after* it is fully initialized.

Timeline & References

- Reported: Upstream (Kernel.org) [kernel bug tracker/patch mailing list]
- Patched: drm/bridge: sii902x: Fix probing race issue
- CVE Directory: CVE-2024-26607 at cve.org
- Discussion: Kernel Patch Discussion on lore.kernel.org

Who’s Affected & What To Do

Who’s affected:
If you’re running mainline Linux or a distribution kernel using the sii902x HDMI bridge (common in some TI-based systems), you might be hit by this if your hardware + kernel version matches.

What to do:

Update your kernel to v6.7.3 or later, or any version with this patch backported.

- If you manage device trees/drivers, ensure deferred probes are handled safely and no device is visible to subsystems before it's fully initialized.

Summary (TL;DR)

- CVE-2024-26607 is a null pointer dereference due to a probe race in the Linux kernel HDMI bridge driver (sii902x).

The fix is simple: only register the bridge when everything’s set up.

- Apply kernel security updates! If you work with embedded TI video/HDMI: check your kernel’s status and backport as necessary.

References

- Upstream Patch
- CVE Record
- Kernel Mailing List Report

For more, check your Linux distro’s security update pages and the kernel.org changelogs. Stay safe!

Timeline

Published on: 02/29/2024 12:15:47 UTC
Last modified on: 01/09/2025 15:27:20 UTC