Skip to main content
VulnerabilityPublished Updated

CVE-2026-74700: Linux kernel · net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers

Affects Linux kernelSource CVE Database V5

0
Compare

Not known to be exploited · CVSS 7.8 High · fixed in d6222af7274f08e7a1848131dc30319993d8f377 : patch Linux kernel soon.

Data as of 30 Oct 2026, 12:49 UTC

CVSS 3.1 base score
7.8High
How severe the flaw is on the 0–10 CVSS scale.

Thin evidence

One scorer or none
CVSS scores by source
CNA (Linux)CVSS 3.17.8
CISA SSVC
Exploitation
No evidence of active exploitation and no public proof of concept
Automatable
Attackers cannot reliably automate steps 1–4 of the kill chain
Technical impact
Total control over the software or total information disclosure

CISA SSVC assessment, 2026-10-16.

Patch
Available – fixed in d6222af7274f08e7a1848131dc30319993d8f377, b648c8a56531aeabd1c14f6b5cf1891e269b3756, a347304b2ca1a5377d5bd2d8a72e4b4f12afe648 +3
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 22 Aug 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 30 Oct 2026.

What to do

Upgrade to a fixed release listed under Affected software.

Affected software

ProductAffectedFixed in
LinuxLinuxAffected
  • ≥ 12db03b65c2b90752e4c37666977fd4a1b5f5824, < d6222af7274f08e7a1848131dc30319993d8f377
Fixed in
  • d6222af7274f08e7a1848131dc30319993d8f377
LinuxLinuxAffected
  • ≥ 12db03b65c2b90752e4c37666977fd4a1b5f5824, < b648c8a56531aeabd1c14f6b5cf1891e269b3756
Fixed in
  • b648c8a56531aeabd1c14f6b5cf1891e269b3756
LinuxLinuxAffected
  • ≥ 12db03b65c2b90752e4c37666977fd4a1b5f5824, < a347304b2ca1a5377d5bd2d8a72e4b4f12afe648
Fixed in
  • a347304b2ca1a5377d5bd2d8a72e4b4f12afe648
LinuxLinuxAffected
  • ≥ 12db03b65c2b90752e4c37666977fd4a1b5f5824, < a81f9c44d87fb59d99fce72e29e02cab3a49a1c3
Fixed in
  • a81f9c44d87fb59d99fce72e29e02cab3a49a1c3
LinuxLinuxAffected
  • ≥ 12db03b65c2b90752e4c37666977fd4a1b5f5824, < 73e8544e0df5d11b1914bcc25ae284946b51786d
Fixed in
  • 73e8544e0df5d11b1914bcc25ae284946b51786d
LinuxLinuxAffected
  • ≥ 12db03b65c2b90752e4c37666977fd4a1b5f5824, < 34e77d8e3570f9df3952496ddb402833695662fd
Fixed in
  • 34e77d8e3570f9df3952496ddb402833695662fd

Description

In the Linux kernel, the following vulnerability has been resolved: net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers Another challenge with unlocked filters. There is a short window in tc_new_tfilter where a tcf_proto can be found and briefly referenced by a totally unrelated, unlocked classifier's request and cause a race. Feng created a poc which created this race with two threads, one creating a u32 filter and other a flower filter in the same chain/prio: 1. Both threads enter tc_new_tfilter, both find the chain empty, both drop filter_chain_lock 2. u32 finishes tcf_proto_create("u32") first, calls tcf_chain_tp_insert_unique() -> inserts u32_tp into the chain 3. flower finishes tcf_proto_create("flower") later, calls tcf_chain_tp_insert_unique() -> tcf_chain_tp_find() now sees u32_tp already there, takes a reference on it, destroys flower's own tp_new and returns u32_tp to the caller. Flower then hits the kind mismatch check (because it requested for kind "flower" but tp->ops->kind is "u32") and goes through the errout path which calls tcf_proto_put() on u32_tp. If the u32 thread has already gone through its own errout (its change() call failed on the PoC's empty options) and dropped its create and insert refs, flower's put is the last one and drops u32_tp's refcnt to zero. At this point tp->ops->destroy() runs in a context that never took rtnl_lock. When that happens, it might cause a UAF like the following (illustrated by the PoC): [ +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393) [ +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524 Call Trace: u32_init (net/sched/cls_u32.c:393) tc_new_tfilter (net/sched/cls_api.c:2378) Allocated by task 526: u32_init (net/sched/cls_u32.c:378) tc_new_tfilter (net/sched/cls_api.c:2378) Freed by task 522: kfree u32_destroy (net/sched/cls_u32.c:662) tcf_proto_destroy (net/sched/cls_api.c:446) tcf_proto_put (net/sched/cls_api.c:459) tc_new_tfilter (net/sched/cls_api.c:2459) Fix this by having tcf_proto_destroy() take rtnl_lock around tp->ops->destroy() for locked classifiers whenever rtnl is not held. To explain why I used a temp variable "not_lockless" I'd like to point to a semi-related note on rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (adding here for future cleanup if deemed necessary): The rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are redundant sources of truth for whether rtnl_lock is held. Among the nine classifier destroy(..rtnl_held..) callbacks, only flower consults the rtnl_held parameter which it propagates to tc_setup_cb_destroy() and tc_setup_cb_call(). The other eight (u32, flow, bpf, cgroup, route, basic, fw, mall) ignore it entirely;-> those that call tc_setup_cb_destroy() (u32, bpf, mall) hardcode true always instead of forwarding the parameter. A future cleanup should remove the rtnl_held parameter from the destroy callback signature entirely and have callers rely solely on their knowledge whether they are running in an unlocked context.

References

Community reviews

Loading reviews…