VYPR
Unrated severityNVD Advisory· Published Jun 9, 2026

CVE-2026-46319

CVE-2026-46319

Description

Linux kernel UAF in act_ct allows privilege escalation due to a race condition in RCU lock handling.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Linux kernel UAF in act_ct allows privilege escalation due to a race condition in RCU lock handling.

Vulnerability

A use-after-free vulnerability exists in the Linux kernel's net/sched: act_ct component. Specifically, in the tcf_ct_flow_table_get() function, rhashtable_lookup_fast() performs an RCU read lock and unlock before returning a flow table entry (ct_ft). This creates a race window where tcf_ct_flow_table_cleanup_work() can free the ct_ft object before its reference count is incremented, leading to a use-after-free.

Exploitation

An attacker needs to trigger a race condition between the rhashtable_lookup_fast() call and the refcount_inc_not_zero() check within tcf_ct_flow_table_get(). If the ct_ft object is freed by tcf_ct_flow_table_cleanup_work() after the RCU read lock is released but before the reference count is incremented, the subsequent use of the freed ct_ft object will occur.

Impact

Successful exploitation of this vulnerability can lead to a use-after-free condition, which can be leveraged by an attacker to achieve privilege escalation on the affected system.

Mitigation

This vulnerability has been resolved in the Linux kernel. The fix ensures that the RCU read lock is held until after the reference count is successfully incremented on the flow table entry. The specific fixed version and release date are available in the provided reference [1].

AI Insight generated on Jun 9, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

16
3e20e1b3058e

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 7.0.10via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 7d5e50c921a07..6158e13c98d35 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc_obj(*ct_ft);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
f462dca0c841

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 7.1-rc1via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 7d5e50c921a07..6158e13c98d35 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc_obj(*ct_ft);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
17dfb67cb399

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 6.12.91via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 945b64be4c1f1..c82755749211c 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -326,9 +326,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
4c727c6967a4

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 6.18.33via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index b3c160ad590d2..f9cb8f7474ed3 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -326,9 +326,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
ece578ca61e5

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 5.10.258via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index d75f4b2b97daa..adb421684440a 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -289,9 +289,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
a2e0c045c87a

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 5.15.209via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 171ebf4594793..1639cc2869ef1 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -290,9 +290,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
67c9ecc9f257

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 6.1.175via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 75a8fba9fa57a..651701a186fec 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -324,9 +324,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
f23424a0ddad

net/sched: act_ct: Only release RCU read lock after ct_ft

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJamal Hadi SalimApr 10, 2026Fixed in 6.6.141via kernel-cna
1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index a5f4a27c8dd31..7810c9d64ff3a 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
a2e0c045c87a

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 171ebf4594793..1639cc2869ef1 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -290,9 +290,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
4c727c6967a4

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index b3c160ad590d2..f9cb8f7474ed3 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -326,9 +326,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
3e20e1b3058e

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 7d5e50c921a07..6158e13c98d35 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc_obj(*ct_ft);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
67c9ecc9f257

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 75a8fba9fa57a..651701a186fec 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -324,9 +324,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
17dfb67cb399

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 945b64be4c1f1..c82755749211c 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -326,9 +326,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
ece578ca61e5

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index d75f4b2b97daa..adb421684440a 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -289,9 +289,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
f23424a0ddad

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index a5f4a27c8dd31..7810c9d64ff3a 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc(sizeof(*ct_ft), GFP_KERNEL);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    
f462dca0c841

net/sched: act_ct: Only release RCU read lock after ct_ft

1 file changed · +6 3
  • net/sched/act_ct.c+6 3 modified
    diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
    index 7d5e50c921a07..6158e13c98d35 100644
    --- a/net/sched/act_ct.c
    +++ b/net/sched/act_ct.c
    @@ -328,9 +328,13 @@ static int tcf_ct_flow_table_get(struct net *net, struct tcf_ct_params *params)
     	int err = -ENOMEM;
     
     	mutex_lock(&zones_mutex);
    -	ct_ft = rhashtable_lookup_fast(&zones_ht, &key, zones_params);
    -	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref))
    +	rcu_read_lock();
    +	ct_ft = rhashtable_lookup(&zones_ht, &key, zones_params);
    +	if (ct_ft && refcount_inc_not_zero(&ct_ft->ref)) {
    +		rcu_read_unlock();
     		goto out_unlock;
    +	}
    +	rcu_read_unlock();
     
     	ct_ft = kzalloc_obj(*ct_ft);
     	if (!ct_ft)
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Synthesis attempt was rejected by the grounding validator. Re-run pending.

References

8

News mentions

1