CVE-2024-27399 - Null Pointer Dereference Race in Linux Bluetooth l2cap_chan_timeout (Explained for Everyone)

- [Code Snippets/Diff](#code)

[Summary for Users](#summary)

What is CVE-2024-27399?

CVE-2024-27399 is a recently fixed vulnerability in the Linux kernel's Bluetooth stack (specifically, the L2CAP protocol). It occurs due to a race condition in how L2CAP channel timeouts and deletions are managed. When two functions—l2cap_chan_timeout() (which cleans up old connections after a timeout) and l2cap_chan_del() (which deletes a channel)—run at the same time, it’s possible to end up following a pointer that's just been set to NULL. This causes a kernel null pointer dereference.

This kind of bug can crash your Linux system or lead to local privilege escalation under some circumstances.


The Technical Details

The core problem is a race between two threads accessing or modifying an l2cap_chan structure.

The Bluetooth L2CAP code manages "channels" for each logical connection.

- If a channel is deleted (via l2cap_chan_del()), its internal pointer chan->conn is set to NULL.
- But at almost the same time, if the timeout handler (l2cap_chan_timeout()) is working, it might still try to use this chan->conn pointer, not knowing it's already set to NULL.
- If it tries to lock (with mutex_lock) what's really just a NULL pointer, the kernel instantly panics.

Example stack trace from the kernel when this happens

BUG: KASAN: null-ptr-deref in mutex_lock+x68/xc
Write of size 8 at addr 0000000000000158 by task kworker/:/7

...
Disabling lock debugging due to kernel taint
BUG: kernel NULL pointer dereference, address: 0000000000000158
#PF: supervisor write access in kernel mode
Oops: 0002 [#1] PREEMPT SMP KASAN NOPTI
...
Workqueue: events l2cap_chan_timeout
RIP: 001:mutex_lock+x88/xc
Code: ... 

This KASAN (Kernel Address Sanitizer) report means an attempt was made to lock a NULL mutex through chan->conn.


Here's a simple illustration in pseudocode

// This is a simplification of the real kernel flow

struct l2cap_chan {
    struct l2cap_conn *conn;
    // ...
};

void l2cap_chan_del(struct l2cap_chan *chan) {
    // Deletes connection
    chan->conn = NULL;
    // ...
}

void l2cap_chan_timeout(struct work_struct *work) {
    struct l2cap_chan *chan = ...; // (from work_struct)
    // BAD: If l2cap_chan_del() just ran, conn is now NULL!
    mutex_lock(&chan->conn->lock); // <-- kernel crash if conn == NULL!
    // ...
}

If l2cap_chan_timeout() comes right after and tries to use chan->conn, it crashes.

This is the type of classic "use-after-free or NULL" issue that occurs in multi-threaded code if you don't synchronize access.


How an Exploit Could Work

This bug lives in kernel space, not userspace. You can't trigger it with a webpage or local process—unless you can trigger L2CAP connections and manipulations from userspace. A Proof-of-Concept (PoC) might do this using BlueZ (Linux Bluetooth stack) and a local script:

Open many L2CAP connections to the local Bluetooth subsystem.

- Force repeated disconnects and timeouts at very high speed, so that l2cap_chan_timeout and l2cap_chan_del race each other.
- Eventually, you'll hit the window where one thread sets chan->conn=NULL just as another tries to use it.

A generic PoC in C (over-simplified)

// Pseudo/Not fully working! For illustration ONLY
int main() {
    for(int i=; i < 100; i++) {
        connect_l2cap(); // open channel
        set_timeout_short(); // ensure timeout handler will run
        disconnect_channel(); // trigger deletion simultaneously
    }
}

Result: Kernel panic, system crash, possible DoS.

Impact: This is a Denial-of-Service bug, NOT a direct privilege escalation. However, in some contexts, a kernel crash might allow more dangerous exploits if attackers can combine this with other vulnerabilities.


Mitigation and Fixes

Status: The issue is fixed in mainline Linux as of April 2024. Kernel versions 6.9.-rc6 and later have the patch.

The Fix: Proper locks and checks were added to make sure that l2cap_chan_timeout() carefully checks if chan->conn is valid (not NULL) before trying to lock or use it.

Distros: Backport the patch to all supported kernel versions.

- Embedded/Bluetooth devs: Never trust a pointer's value in a racey context!


Patch Discussion and Upstream Commit:

- Linux Bluetooth L2CAP patch
- Syzkaller bug report (KASAN)

CVE entry:

- CVE-2024-27399 at NVD

Red Hat Security Bug:

- Red Hat Bugzilla - 2271258


Before

static void l2cap_chan_timeout(struct work_struct *work)
{
    struct l2cap_chan *chan = ...;
    mutex_lock(&chan->conn->lock);
    // ...
}

After

static void l2cap_chan_timeout(struct work_struct *work)
{
    struct l2cap_chan *chan = ...;
    if (!chan->conn)
        return;
    mutex_lock(&chan->conn->lock);
    // ...
}

Or even more robust (pseudocode)

struct l2cap_conn *conn = chan->conn;

if (!conn)
    return;

mutex_lock(&conn->lock);
// ...

This check is simple but crucial: always check a pointer before using it, especially when racing with other threads.


Summary for Users

- CVE-2024-27399 is a bug in Linux Bluetooth that could let attackers crash your system if they rapidly open/close L2CAP channel connections.

Fix is available. Update your kernel if you use Linux Bluetooth!

- The real risk: Denial of Service (DoS)—remote crashes possible if you expose Bluetooth to untrusted devices.
- Developers: Always add checks for NULL pointers and consider locking strategies to avoid race conditions.


Stay safe! Keep your kernel patched.
For more details, see the official patch commit.


*Post written and summarized exclusively for your query by an AI, based on current Linux kernel sources and CVE reports*

Timeline

Published on: 05/14/2024 15:12:28 UTC
Last modified on: 05/04/2025 09:04:11 UTC