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

Published Aug 22, 2026
·
Updated

In the Linux kernel, the following vulnerability has been resolved:

net/sched: clsapi: Always acquire rtnllock when destroying locked classifiers

Another challenge with unlocked filters. There is a short window in tcnewtfilter where a tcfproto 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 tcnewtfilter, both find the chain empty, both drop filterchainlock 2. u32 finishes tcfprotocreate("u32") first, calls tcfchaintpinsertunique() -> inserts u32tp into the chain 3. flower finishes tcfprotocreate("flower") later, calls tcfchaintpinsertunique() -> tcfchaintpfind() now sees u32tp already there, takes a reference on it, destroys flower's own tpnew and returns u32tp 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 tcfprotoput() on u32tp. 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 u32tp's refcnt to zero.

At this point tp->ops->destroy() runs in a context that never took rtnllock. When that happens, it might cause a UAF like the following (illustrated by the PoC):

[ +0.000710] BUG: KASAN: slab-use-after-free in u32init (net/sched/clsu32.c:393) [ +0.000281] Read of size 8 at addr ffff888120022f00 by task pocfengxue/524

Call Trace: u32init (net/sched/clsu32.c:393) tcnewtfilter (net/sched/clsapi.c:2378)

Allocated by task 526: u32init (net/sched/clsu32.c:378) tcnewtfilter (net/sched/clsapi.c:2378)

Freed by task 522: kfree u32destroy (net/sched/clsu32.c:662) tcfprotodestroy (net/sched/clsapi.c:446) tcfprotoput (net/sched/clsapi.c:459) tcnewtfilter (net/sched/clsapi.c:2459)

Fix this by having tcfprotodestroy() take rtnllock around tp->ops->destroy() for locked classifiers whenever rtnl is not held.

To explain why I used a temp variable "notlockless" I'd like to point to a semi-related note on rtnlheld vs TCFPROTOOPSDOITUNLOCKED (adding here for future cleanup if deemed necessary): The rtnlheld parameter and the TCFPROTOOPSDOITUNLOCKED flag are redundant sources of truth for whether rtnllock is held. Among the nine classifier destroy(..rtnlheld..) callbacks, only flower consults the rtnlheld parameter which it propagates to tcsetupcbdestroy() and tcsetupcbcall(). The other eight (u32, flow, bpf, cgroup, route, basic, fw, mall) ignore it entirely;-> those that call tcsetupcbdestroy() (u32, bpf, mall) hardcode true always instead of forwarding the parameter.

A future cleanup should remove the rtnlheld parameter from the destroy callback signature entirely and have callers rely solely on their knowledge whether they are running in an unlocked context.

Affected Software

1 affected component
Linux Linux kernel

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Update the kernel networking scheduler/classifier code so that tcf_proto_destroy()/classifier destroy(..rtnl_held..) paths always take rtnl_lock around destroy for locked classifiers when rtnl is not held; this corresponds to the resolution statement: "Fix this by having tcf_proto_destroy() take rtnl_lock around Flower" and "net/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers whenever rtnl is not held."

    net/sched: cls_api (tcf_proto_destroy / classifier destroy path) rtnl_held parameter handling and rtnl lock acquisition = Always acquire rtnl_lock when destroying locked classifiers whenever rtnl is not held (per fix text)
  2. Configuration

    Ensure destroy callbacks correctly handle the TCF_PROTO_OPS_DOIT_UNLOCKED/rtnl_held relationship so destroy of locked classifiers is done with rtnl_lock held; the text states both the rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are involved in the race/UAF and should be treated consistently.

    net/sched: cls_api / tcf_proto_destroy destroy callback TCF_PROTO_OPS_DOIT_UNLOCKED usage = Respect locked/unlocked context to avoid destroying without required rtnl_lock

Event History

Aug 22, 2026
CVE Published
via MITRE·03:33 PM
Data Sourced
via MITRE·03:33 PM
Description
Data Sourced
via NVD·04:16 PM
Description

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203