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.
Published: 2026-08-22
Score: 7.8 High
EPSS: < 1% Very Low
KEV: No
Impact: Kernel memory corruption that may allow arbitrary code execution
Action: Immediate Patch
AI Analysis

Impact

This flaw is a race condition in the Linux kernel’s traffic‑control (tc) classifier creation routine. During the destruction of a classifier, the kernel may skip acquiring the required rtnl_lock, leading to a use‑after‑free of the classifier’s private data. This can lead to kernel memory corruption that may allow arbitrary code execution or cause a system crash (inferred).

Affected Systems

All Linux kernel releases that include the traffic‑control scheduler code and have not yet incorporated the commit that enforces rtnl_lock during classifier destruction are at risk. The vulnerability applies to any kernel built before that locking safeguard was added.

Risk and Exploitability

The flaw requires the ability to invoke the tc subsystem, which in practice needs local, privileged access (inferred). The likely attack vector is by submitting two concurrent tc filter commands that create different filter types in the same chain, thereby triggering the race (inferred). No public exploits are reported, the vulnerability is not listed in CISA’s KEV catalog, and its EPSS score is <1%, indicating a low but non‑zero probability of exploitation. The CVSS score of 7.8 denotes moderate severity, but because the issue results in kernel memory corruption, the risk is high for an attacker with local privilege.

Generated by OpenCVE AI on August 25, 2026 at 07:38 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Apply a kernel update that includes the patch adding rtnl_lock acquisition during classifier destruction.
  • If an immediate kernel patch is unavailable, restrict the use of the ‘tc’ utility to trusted or privileged users only to reduce the attack surface.
  • After applying the update, reboot the affected systems so that the patched kernel image is loaded and active.

Generated by OpenCVE AI on August 25, 2026 at 07:38 UTC.

Tracking

Sign in to view the affected projects.

Advisories
Source ID Title
Debian DSA Debian DSA DSA-6466-1 linux security update
History

Tue, 25 Aug 2026 06:00:00 +0000

Type Values Removed Values Added
Metrics 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'}

cvssV3_1

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


Mon, 24 Aug 2026 15:15:00 +0000

Type Values Removed Values Added
Weaknesses CWE-362
CWE-416

Mon, 24 Aug 2026 12:15:00 +0000

Type Values Removed Values Added
Weaknesses CWE-763
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

Moderate


Sat, 22 Aug 2026 19:30:00 +0000

Type Values Removed Values Added
Weaknesses CWE-362
CWE-416

Sat, 22 Aug 2026 15:45:00 +0000

Type Values Removed Values Added
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.
Title net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers
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-08-25T05:41:42.546Z

Reserved: 2026-08-15T05:44:03.927Z

Link: CVE-2026-74700

cve-icon Vulnrichment

No data.

cve-icon NVD

Status : Received

Published: 2026-08-22T16:16:44.610

Modified: 2026-08-25T06:18:53.597

Link: CVE-2026-74700

cve-icon Redhat

Severity : Moderate

Publid Date: 2026-08-22T00:00:00Z

Links: CVE-2026-74700 - Bugzilla

cve-icon OpenCVE Enrichment

Updated: 2026-08-25T07:45:04Z

Weaknesses
  • CWE-763

    Release of Invalid Pointer or Reference