HIGH 7.8

CVE-2026-46319: Linux Kernel act_ct Use-After-Free Privilege Escalation

A use-after-free vulnerability exists in the Linux kernel's traffic control act_ct module. When a traffic control policy is initialized, the code looks up a flow table object and then attempts to increment its reference counter—but between the lookup and the increment, the object can be freed by a separate cleanup process. An attacker with local access could exploit this race condition to cause a kernel crash or execute code with elevated privileges. The vulnerability requires precise timing to trigger but is feasible in environments where multiple processes interact with traffic control policies simultaneously.

Source data · NVD / CISA · public domain

CVSS
3.1 · 7.8 HIGH · CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weaknesses (CWE)
CWE-416
Affected products
1 configuration(s)
Published / Modified
2026-06-09 / 2026-07-08

NVD description (verbatim)

In the Linux kernel, the following vulnerability has been resolved: net/sched: act_ct: Only release RCU read lock after ct_ft When looking up a flow table in act_ct in tcf_ct_flow_table_get(), rhashtable_lookup_fast() internally opens and closes an RCU read critical section before returning ct_ft. The tcf_ct_flow_table_cleanup_work() can complete before refcount_inc_not_zero() is invoked on the returned ct_ft resulting in a UAF on the already freed ct_ft object. This vulnerability can lead to privilege escalation. Analysis from [email protected]: When initializing act_ct, tcf_ct_init() is called, which internally triggers tcf_ct_flow_table_get(). static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params) { struct zones_ht_key key = { .net = net, .zone = params->zone }; struct tcf_ct_flow_table *ct_ft; int err = -ENOMEM; mutex_lock(&zones_mutex); ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params); // [1] if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) // [2] goto out_unlock; ... } static __always_inline void *rhashtable_lookup_fast( struct rhashtable *ht, const void *key, const struct rhashtable_params params) { void *obj; rcu_read_lock(); obj = rhashtable_lookup(ht, key, params); rcu_read_unlock(); return obj; } At [1], rhashtable_lookup_fast() looks up and returns the corresponding ct_ft from zones_ht . The lookup is performed within an RCU read critical section through rcu_read_lock() / rcu_read_unlock(), which prevents the object from being freed. However, at the point of function return, rcu_read_unlock() has already been called, and there is nothing preventing ct_ft from being freed before reaching refcount_inc_not_zero(&ct_ft->ref) at [2]. This interval becomes the race window, during which ct_ft can be freed. Free Process: tcf_ct_flow_table_put() is executed through the path tcf_ct_cleanup() call_rcu() tcf_ct_params_free_rcu() tcf_ct_params_free() tcf_ct_flow_table_put(). static void tcf_ct_flow_table_put(struct tcf_ct_flow_table *ct_ft) { if (refcount_dec_and_test(&ct_ft->ref)) { rhashtable_remove_fast(&zones_ht, &ct_ft->node, zones_params); INIT_RCU_WORK(&ct_ft->rwork, tcf_ct_flow_table_cleanup_work); // [3] queue_rcu_work(act_ct_wq, &ct_ft->rwork); } } At [3], tcf_ct_flow_table_cleanup_work() is scheduled as RCU work static void tcf_ct_flow_table_cleanup_work(struct work_struct *work) { struct tcf_ct_flow_table *ct_ft; struct flow_block *block; ct_ft = container_of(to_rcu_work(work), struct tcf_ct_flow_table, rwork); nf_flow_table_free(&ct_ft->nf_ft); block = &ct_ft->nf_ft.flow_block; down_write(&ct_ft->nf_ft.flow_block_lock); WARN_ON(!list_empty(&block->cb_list)); up_write(&ct_ft->nf_ft.flow_block_lock); kfree(ct_ft); // [4] module_put(THIS_MODULE); } tcf_ct_flow_table_cleanup_work() frees ct_ft at [4]. When this function executes between [1] and [2], UAF occurs. This race condition has a very short race window, making it generally difficult to trigger. Therefore, to trigger the vulnerability an msleep(100) was inserted after[1]

8 reference(s) · View on NVD →

SEC.co analysis · AI-assisted, reviewed against source

Technical summary

The vulnerability is a use-after-free (CWE-416) in the Linux kernel's net/sched/act_ct module, specifically in the interaction between tcf_ct_flow_table_get() and tcf_ct_flow_table_cleanup_work(). The root cause is a race condition between two RCU-protected operations: rhashtable_lookup_fast() internally releases its RCU read lock before returning the flow table pointer, creating an unprotected window between the lookup and the subsequent refcount_inc_not_zero() call. During this window, a parallel cleanup path initiated by tcf_ct_flow_table_put() can execute tcf_ct_flow_table_cleanup_work(), which deallocates the flow table object via kfree(). If cleanup occurs in this race window, the refcount increment operates on freed memory. The analysis indicates the race window is normally too narrow to trigger reliably, but becomes exploitable under conditions where process scheduling or explicit delays amplify the timing gap.

Business impact

Successful exploitation enables local privilege escalation, allowing an unprivileged user to gain kernel-level code execution. This bypasses access controls and can lead to complete system compromise, data exfiltration, malware persistence, or denial of service. In containerized or shared-tenancy environments, the impact is amplified, as a guest or container user could compromise the host kernel. Organizations running susceptible kernel versions face elevated risk if they operate multi-tenant systems or allow unprivileged user workloads on production infrastructure.

Affected systems

The Linux kernel is affected. Exploitation requires local access and the ability to interact with traffic control (tc) subsystem facilities, typically available to unprivileged users via netlink sockets. Verify the specific affected kernel versions and any distribution-specific backports against the Linux kernel security advisory and your vendor's advisories. Containerized deployments, where unprivileged container processes can invoke tc operations, are at particular risk.

Exploitability

Exploitability is classified as high despite a narrow race window. The vulnerability requires local user-level access and does not require special privileges to trigger initial setup of traffic control policies. The race window is normally microseconds but can be reliably widened through kernel module insertion or crafted timing—the published analysis explicitly demonstrates this via msleep(). No in-the-wild exploitation is confirmed at publication, but the technique is well understood by the researcher community. Automated fuzzing and race condition detection tools are likely to surface this issue in testing pipelines.

Remediation

The core fix requires ensuring the RCU read-side critical section remains active from the lookup until after the reference count is safely incremented. This involves restructuring tcf_ct_flow_table_get() to hold the RCU lock across both the hashtable lookup and the refcount operation, or alternatively, adopting a synchronization mechanism that prevents cleanup during the vulnerable window. Patch details and exact code changes should be verified against the upstream Linux kernel commit and your distributor's advisory, as backport variations exist.

Patch guidance

Linux users should apply kernel updates provided by their distribution or upstream as soon as they become available. Check the Linux kernel security advisories and your vendor's security bulletins for specific patched versions and release dates. If you run a self-compiled kernel, monitor lkml and kernel.org for the upstream fix. In the interim, if feasible, restrict unprivileged access to traffic control operations via userspace policy (e.g., seccomp, AppArmor, or SELinux policies limiting netlink socket access), though this is not a complete mitigation.

Detection guidance

Monitor for attempts to use traffic control (tc) commands or netlink syscalls by unprivileged processes, particularly repeated calls to tcf_ct_init() or manipulation of flow table zones. Kernel logging and BPF-based observability can capture netlink policy change events. Look for kernel warnings, UAF detections via KASAN if enabled, or unexpected kernel panics correlated with tc operations. In production, enable CONFIG_KASAN and CONFIG_KASAN_GENERIC if resources permit, to catch heap corruption at runtime. Audit logs showing tc or netlink activity from unexpected users warrant investigation.

Why prioritize this

This vulnerability earns HIGH priority due to the combination of: (1) local privilege escalation capability affecting kernel integrity, (2) exploitability within reach of unprivileged users without requiring race condition amplification techniques in multi-process or scheduler-friendly scenarios, and (3) broad applicability across Linux distributions and versions. While the race window is narrow, it is deterministically triggerable and well-documented. Organizations with multi-user or containerized systems should treat this as urgent.

Risk score, explained

The CVSS 3.1 score of 7.8 (HIGH) reflects: Attack Vector: Local (AV:L), reflecting that local user access is required; Attack Complexity: Low (AC:L), as the race condition, while timing-sensitive, does not require privilege escalation beforehand or complex environmental setup; Privileges Required: Low (PR:L), as unprivileged users can invoke tc operations; User Interaction: None (UI:N); Scope: Unchanged (S:U); Confidentiality, Integrity, and Availability all High (C:H/I:H/A:H), because successful exploitation yields kernel code execution with full system access, enabling data theft, unauthorized modification, and denial of service.

Frequently asked questions

Can this be exploited remotely?

No. The vulnerability requires local user-level access to invoke traffic control operations. Remote exploitation is not possible; however, in cloud or shared hosting scenarios, any tenant with local shell access poses a threat.

Do I need root privileges to trigger this vulnerability?

No. Unprivileged users can invoke traffic control (tc) commands and netlink syscalls that exercise the vulnerable code path. However, the impact of successful exploitation is kernel code execution, effectively granting root-equivalent privileges.

Is there a workaround if I cannot patch immediately?

Partial mitigation is possible by restricting unprivileged user access to traffic control operations via kernel security modules (AppArmor, SELinux) or seccomp filters that block netlink socket operations. This does not fix the vulnerability but reduces attack surface. Comprehensive patching remains the recommended solution.

How does this differ from other use-after-free bugs?

This UAF is distinctive because it arises from RCU-protected data structures where the RCU lock scope is incorrectly bounded. The vulnerability exploits the assumption that a pointer returned from an RCU-protected lookup remains valid, when in fact the RCU unlock within rhashtable_lookup_fast() allows deallocation before the caller increments the reference count. Understanding this pattern is important for audit of other RCU-dependent subsystems.

This analysis is based on the vendor advisory, published CVE description, and third-party security research. Specific patch version numbers, release dates, and affected kernel versions should be verified directly against the Linux kernel security advisory, your distribution's security bulletins, and lkml announcements. SEC.co does not provide exploit code or weaponization guidance. Organizations should validate patch applicability in their environment before deployment. This information is provided for defensive security purposes only. Source: NVD (public-domain), retrieved 2026-07-16. Analysis generated by SEC.co (claude-haiku-4-5).