Description
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 zdi-disclosures@trendmicro.com:
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]
Published: 2026-06-09
Score: 7.0 High
EPSS: n/a
KEV: No
Impact: n/a
Action: n/a
AI Analysis

Impact

In the Linux kernel, the act_ct classifier uses a flow table that is looked up via an RCU‑protected rhashtable. The code releases the RCU lock before incrementing the reference count. A race exists in which the table entry can be freed by cleanup work queued through call_rcu, so that the reference count is still incremented after the object has been freed. This causes a use‑after‑free that allows an attacker to execute arbitrary code in kernel mode. The flaw is a classic Use‑After‑Free (CWE‑416) and can lead to privilege escalation.

Affected Systems

The vulnerability affects any Linux kernel that has act_ct enabled, which is common on systems that use the ‘tc’ traffic control classifier to match on connection‑tracking state. All distributions shipping a kernel with the net/sched act_ct implementation are potentially vulnerable until the upstream fix is backported. Devices such as routers or virtual machines that load the act_ct module for QoS or traffic shaping are also at risk.

Risk and Exploitability

No publicly known exploit and the race window is very small, making manual exploitation difficult; no EPSS score is available. The CVSS score is 7.0, indicating a high severity because kernel privilege escalation is possible. The issue is not in the CISA KEV catalog yet. Until a vendor releases a patch, the risk remains significant, but triggering the flaw requires privileged access or elevated capabilities to create the race scenario.

Generated by OpenCVE AI on June 10, 2026 at 02:12 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Apply the latest Linux kernel release that contains the act_ct race condition fix.
  • If an immediate kernel upgrade is not possible, disable act_ct functionality by unloading the module or removing the tc act_ct classifier from the network configuration.
  • Configure audit or monitoring to flag any unexpected rcu work or ct_ft frees that might indicate an ongoing attempt to exploit the race window.

Generated by OpenCVE AI on June 10, 2026 at 02:12 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Wed, 10 Jun 2026 02:30:00 +0000

Type Values Removed Values Added
Weaknesses CWE-416

Wed, 10 Jun 2026 00:15:00 +0000

Type Values Removed Values Added
Weaknesses CWE-826
References
Metrics threat_severity

None

cvssV3_1

{'score': 7.0, 'vector': 'CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H'}

threat_severity

Important


Tue, 09 Jun 2026 13:45:00 +0000

Type Values Removed Values Added
Weaknesses CWE-416

Tue, 09 Jun 2026 12:30:00 +0000

Type Values Removed Values Added
Description 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 zdi-disclosures@trendmicro.com: 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]
Title net/sched: act_ct: Only release RCU read lock after ct_ft
First Time appeared Linux
Linux linux Kernel
CPEs cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
Vendors & Products Linux
Linux linux Kernel
References

Subscriptions

Linux Linux Kernel
cve-icon MITRE

Status: PUBLISHED

Assigner: Linux

Published:

Updated: 2026-06-09T12:11:12.128Z

Reserved: 2026-05-13T15:03:33.112Z

Link: CVE-2026-46319

cve-icon Vulnrichment

No data.

cve-icon NVD

Status : Received

Published: 2026-06-09T13:16:37.210

Modified: 2026-06-09T13:16:37.210

Link: CVE-2026-46319

cve-icon Redhat

Severity : Important

Publid Date: 2026-06-09T00:00:00Z

Links: CVE-2026-46319 - Bugzilla

cve-icon OpenCVE Enrichment

Updated: 2026-06-10T02:15:19Z

Weaknesses