CVE-2023-4208 Overview
CVE-2023-4208 is a use-after-free vulnerability [CWE-416] in the Linux kernel's net/sched: cls_u32 traffic classifier component. Local attackers can exploit this flaw to escalate privileges on affected systems. The issue occurs when u32_change() updates an existing filter bound to a class. The function copies the entire tcf_result struct into the new filter instance and then calls tcf_unbind_filter() on the old instance in the success path. This decrements filter_cnt of a still-referenced class, allowing it to be deleted while references remain. The result is a use-after-free condition exploitable for local privilege escalation. The fix is included in upstream commit 3044b16e7c6fe5d24b1cdbcf1bd0a9d92d1ebd81.
Critical Impact
A local unprivileged user with CAP_NET_ADMIN in a user namespace can trigger memory corruption in the kernel traffic control subsystem to obtain root privileges.
Affected Products
- Linux kernel (multiple versions prior to fix commit 3044b16e7c6fe5d24b1cdbcf1bd0a9d92d1ebd81)
- Debian Linux 12.0 (bookworm)
- Distributions shipping vulnerable kernels addressed via DSA-5492 and Debian LTS
Discovery Timeline
- 2023-09-06 - CVE-2023-4208 published to the National Vulnerability Database (NVD)
- 2025-02-13 - Last updated in NVD database
Technical Details for CVE-2023-4208
Vulnerability Analysis
The vulnerability resides in the cls_u32 classifier, part of the kernel's traffic control (tc) subsystem under net/sched. The u32 classifier matches packets based on arbitrary byte offsets and bitmasks. Filters can be bound to a traffic control class through the tcf_result structure, which holds a reference to the target class and increments its filter_cnt counter.
When an existing u32 filter is updated through u32_change(), the kernel allocates a new filter instance and copies the entire tcf_result struct from the old filter. The copy duplicates the class pointer without incrementing a new reference. On the success path, the kernel calls tcf_unbind_filter() on the old filter instance. This decrements filter_cnt on the referenced class, even though the new filter instance still points to that class.
With filter_cnt artificially decreased, the bound class becomes eligible for deletion while a live reference exists in the new filter. Subsequent classifier operations dereference freed memory, producing a classic use-after-free.
Root Cause
The root cause is an unbalanced reference accounting bug. u32_change() duplicates the class binding by copying tcf_result but unconditionally unbinds the old filter, releasing one reference for a binding that still has a consumer.
Attack Vector
Exploitation is local and requires the ability to create and modify tc filters. This capability is exposed to unprivileged users inside a user namespace where CAP_NET_ADMIN is granted over the namespace's network. An attacker creates a u32 filter bound to a class, triggers u32_change() to update it, then forces deletion of the now under-referenced class. Reclaiming the freed slab object with controlled data enables kernel memory corruption and privilege escalation. See the Linux kernel commit for the corrected reference handling logic.
Detection Methods for CVE-2023-4208
Indicators of Compromise
- Kernel oops, panic, or KASAN reports referencing u32_change, tcf_unbind_filter, or cls_u32 call paths
- Unexpected tc filter modifications on u32 classifiers originating from unprivileged user sessions
- Process executions invoking tc filter add/change dev ... protocol ... u32 ... from non-administrative accounts
- Creation of unprivileged user namespaces immediately followed by traffic control operations
Detection Strategies
- Monitor execve telemetry for invocations of /sbin/tc or iproute2 binaries by non-root users, particularly inside containers
- Audit unshare(CLONE_NEWUSER|CLONE_NEWNET) syscall sequences followed by tc activity
- Collect kernel ring buffer messages (dmesg) for use-after-free signatures, slab corruption, or general protection faults in network scheduler symbols
- Correlate sudden setuid-to-root transitions following traffic control system calls
Monitoring Recommendations
- Forward auditd records for the tc command and netlink RTM_NEWTFILTER messages to a centralized SIEM
- Alert on kernel crash signatures containing cls_u32, tcf_bind_filter, or tcf_unbind_filter in stack traces
- Track container workloads that create user namespaces with CAP_NET_ADMIN and perform classifier modifications
How to Mitigate CVE-2023-4208
Immediate Actions Required
- Apply the upstream Linux kernel patch from commit 3044b16e7c6fe5d24b1cdbcf1bd0a9d92d1ebd81 or install vendor-provided updates
- Debian users should update to fixed packages described in Debian Security Advisory DSA-5492 and the Debian LTS Announcement
- Inventory all Linux hosts and containers running kernels predating the fix and prioritize multi-tenant systems
- Reboot patched systems to load the corrected kernel image
Patch Information
The upstream fix is in the mainline Linux kernel at commit 3044b16e7c6fe5d24b1cdbcf1bd0a9d92d1ebd81. Details are documented at the Linux kernel commit page and the Kernel Dance backport tracker. Debian shipped fixed kernels through DSA-5492 and subsequent LTS updates. Confirm the running kernel includes the patch using uname -r and the distribution's security tracker.
Workarounds
- Disable unprivileged user namespaces where not required by setting kernel.unprivileged_userns_clone=0 or user.max_user_namespaces=0 via sysctl
- Blacklist the cls_u32 module if traffic control U32 classification is unused: add blacklist cls_u32 to /etc/modprobe.d/ and rebuild initramfs
- Restrict CAP_NET_ADMIN in container runtimes by dropping the capability from default profiles
- Apply seccomp filters to block tc netlink operations from untrusted workloads
# Configuration example
# Disable unprivileged user namespaces
sysctl -w kernel.unprivileged_userns_clone=0
echo 'kernel.unprivileged_userns_clone=0' >> /etc/sysctl.d/99-hardening.conf
# Prevent loading of the vulnerable classifier module
echo 'blacklist cls_u32' > /etc/modprobe.d/disable-cls_u32.conf
# Verify kernel version against patched build
uname -r
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

