CVE-2023-26545 - Double Free Vulnerability in Linux Kernel MPLS - What You Need to Know

The Linux kernel underpins much of the world’s computing, powering everything from smartphones to servers. That’s why security bugs in the kernel get a lot of attention from the tech community. One such bug is CVE-2023-26545, discovered in the MPLS (Multiprotocol Label Switching) networking subsystem of the Linux kernel before version 6.1.13.

In this post, we'll break down what this vulnerability is, why it matters, and walk through the technical details—using simple language and real code snippets.

What is CVE-2023-26545?

CVE-2023-26545 is a double free vulnerability in the Linux kernel’s MPLS code (af_mpls.c). It's triggered when renaming a device _and_ an allocation fails during the process of registering a sysctl table for that device's new location.

"Double free" means that the kernel tries to free (delete) the same chunk of memory twice. This usually results in a crash, but in some cases, it can be exploited for privilege escalation or arbitrary code execution.

To understand this bug, let's look at what the affected code tries to do

- When you rename a network device (think ip link set dev eth name eth1), the MPLS subsystem tries to register its sysctl entries (which help manage runtime kernel parameters) for the new device name.
- If the register_sysctl function fails to allocate the new sysctl table (maybe the system is out of memory), the code tries to clean things up by freeing memory.

However, _it ends up freeing the same sysctl table twice_ due to incomplete error handling.

Here’s a simplified code snippet from net/mpls/af_mpls.c (you can see the real code here):

table = kmemdup(&mpls_dev_table_template, sizeof(table), GFP_KERNEL);
if (!table)
    goto out;

table->data = dev;
err = register_sysctl_table(table);
if (err)
    goto free_table;

// ... rest of function

free_table:
    kfree(table);      // <-- First free
out:
    return err;

// ... somewhere else, in error path
kfree(table);          // <-- Second free!

Problem: If there’s an error and free_table is called, table gets freed. But in out (the general error exit), it's freed _again_. This double free can corrupt the kernel’s memory management.

How Can It Be Exploited?

Any process with sufficient privileges (like root, or perhaps a capability-holding network service) that can rename interfaces can potentially trigger this bug. Example scenario:

1. Try to stress the system so memory allocation for sysctl table fails during interface rename (not trivial, but possible, especially in containers/virtualization).

Repeatedly rename a device with MPLS enabled, causing the faulty cleanup code to run.

3. If attackers can control timing and memory layout, they might exploit the double free to gain code execution in kernel mode.

Note: There’s no known public exploit, but history shows attackers love double free bugs due to their exploitability.

Proof-of-Concept (PoC)

A minimal demonstration—this _cannot_ trivially exploit the system, but here’s a conceptual way to force the vulnerable path (DON’T run as root on a production system!):

# Load the MPLS module (if present)
modprobe mpls_router

# Enable MPLS on a dummy interface
ip link add mpls_test type dummy
sysctl -w net.mpls.platform_labels=100

# Try to rename interface rapidly, possibly under memory pressure
for i in $(seq 1 10000); do
    ip link set mpls_test name mpls_test_$i
    ip link set mpls_test_$i name mpls_test
done

To actually trigger the bug, you’d need memory exhaustion or limits so that register_sysctl_table fails.

Patch and Fix

The bug was fixed in Linux kernel 6.1.13 (commit diff). The patch simply eliminates the double free by setting table = NULL after freeing it, or by ensuring the free operation only happens once.

Advice: Upgrade any Linux kernel below 6.1.13 as soon as you can, especially on systems using the MPLS module.

References and Further Reading

- CVE-2023-26545 at NIST
- Linux Kernel Patch
- Original Source file
- MPLS Howto (Linux Foundation)

Timeline

Published on: 02/25/2023 04:15:00 UTC
Last modified on: 05/03/2023 14:15:00 UTC