{"id":11270,"date":"2026-09-04T18:53:07","date_gmt":"2026-09-04T10:53:07","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-74700"},"modified":"2026-09-04T18:53:07","modified_gmt":"2026-09-04T10:53:07","slug":"cve-2026-74700","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-74700","title":{"rendered":"CVE-2026-74700 [HIGH] &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nnet\/sched: cls_api: A"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>net\/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers<\/p>\n<p>Another challenge with unlocked filters.<br \/>\nThere is a short window in tc_new_tfilter where a tcf_proto can be found<br \/>\nand briefly referenced by a totally unrelated, unlocked classifier&#8217;s request<br \/>\nand cause a race.<\/p>\n<p>Feng created a poc which created this race with two threads, one creating a<br \/>\nu32 filter and other a flower filter in the same chain\/prio:<\/p>\n<p>1. Both threads enter tc_new_tfilter, both find the chain empty, both<br \/>\n   drop filter_chain_lock<br \/>\n2. u32 finishes tcf_proto_create(&#8220;u32&#8221;) first, calls<br \/>\n   tcf_chain_tp_insert_unique() -&gt; inserts u32_tp into the chain<br \/>\n3. flower finishes tcf_proto_create(&#8220;flower&#8221;) later, calls<br \/>\n   tcf_chain_tp_insert_unique() -&gt; tcf_chain_tp_find() now sees u32_tp<br \/>\n   already there, takes a reference on it, destroys flower&#8217;s own tp_new<br \/>\n   and returns u32_tp to the caller.<\/p>\n<p>Flower then hits the kind mismatch check (because it requested for kind<br \/>\n&#8220;flower&#8221; but tp-&gt;ops-&gt;kind is &#8220;u32&#8221;) and goes through the errout path<br \/>\nwhich calls tcf_proto_put() on u32_tp. If the u32 thread has already<br \/>\ngone through its own errout (its change() call failed on the PoC&#8217;s empty<br \/>\noptions) and dropped its create and insert refs, flower&#8217;s put is the<br \/>\nlast one and drops u32_tp&#8217;s refcnt to zero.<\/p>\n<p>At this point tp-&gt;ops-&gt;destroy() runs in a context that never took<br \/>\nrtnl_lock. When that happens, it might cause a UAF like the following<br \/>\n(illustrated by the PoC):<\/p>\n<p>[  +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net\/sched\/cls_u32.c:393)<br \/>\n[  +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue\/524<\/p>\n<p>  Call Trace:<br \/>\n   u32_init (net\/sched\/cls_u32.c:393)<br \/>\n   tc_new_tfilter (net\/sched\/cls_api.c:2378)<\/p>\n<p>  Allocated by task 526:<br \/>\n   u32_init (net\/sched\/cls_u32.c:378)<br \/>\n   tc_new_tfilter (net\/sched\/cls_api.c:2378)<\/p>\n<p>  Freed by task 522:<br \/>\n   kfree<br \/>\n   u32_destroy (net\/sched\/cls_u32.c:662)<br \/>\n   tcf_proto_destroy (net\/sched\/cls_api.c:446)<br \/>\n   tcf_proto_put (net\/sched\/cls_api.c:459)<br \/>\n   tc_new_tfilter (net\/sched\/cls_api.c:2459)<\/p>\n<p>Fix this by having tcf_proto_destroy() take rtnl_lock around<br \/>\ntp-&gt;ops-&gt;destroy() for locked classifiers whenever rtnl is not held.<\/p>\n<p>To explain why I used a temp variable &#8220;not_lockless&#8221; I&#8217;d like to point to a<br \/>\nsemi-related note on rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (adding here<br \/>\nfor future cleanup if deemed necessary):<br \/>\nThe rtnl_held parameter and the TCF_PROTO_OPS_DOIT_UNLOCKED flag are<br \/>\nredundant sources of truth for whether rtnl_lock is held. Among the nine<br \/>\nclassifier destroy(..rtnl_held..) callbacks, only flower consults the<br \/>\nrtnl_held parameter which it propagates to tc_setup_cb_destroy()<br \/>\nand tc_setup_cb_call(). The other eight (u32, flow, bpf, cgroup, route, basic,<br \/>\nfw, mall) ignore it entirely;-&gt; those that call tc_setup_cb_destroy()<br \/>\n(u32, bpf, mall) hardcode true always instead of forwarding the parameter.<\/p>\n<p>A future cleanup should remove the rtnl_held parameter from the destroy callback<br \/>\nsignature entirely and have callers rely solely on their knowledge whether<br \/>\nthey are running in an unlocked context.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>net\/sched: cls_api: Always acquire rtnl_lock when destroying locked classifiers<\/p>\n<p>Another challenge with unlocked filters.<br \/>\nThere is <\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-11270","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/11270","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11270"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11270"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11270"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}