{"id":11224,"date":"2026-09-04T18:51:46","date_gmt":"2026-09-04T10:51:46","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-74621"},"modified":"2026-09-04T18:51:46","modified_gmt":"2026-09-04T10:51:46","slug":"cve-2026-74621","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-74621","title":{"rendered":"CVE-2026-74621 [HIGH] &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nnet\/sched: act_ct: fi"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>net\/sched: act_ct: fix sk_buff leak when the header checks reject a packet<\/p>\n<p>tcf_ct_handle_fragments() runs its header sanity checks before handing<br \/>\nanything to the defragmentation engine:<\/p>\n<p>\tif (family == NFPROTO_IPV4)<br \/>\n\t\terr = tcf_ct_ipv4_is_fragment(skb, &amp;frag);<br \/>\n\telse<br \/>\n\t\terr = tcf_ct_ipv6_is_fragment(skb, &amp;frag);<br \/>\n\tif (err || !frag)<br \/>\n\t\treturn err;<\/p>\n<p>tcf_ct_ipv4_is_fragment() returns -EINVAL or -ENOMEM;<br \/>\ntcf_ct_ipv6_is_fragment() adds -EPROTO when ipv6_find_hdr() fails. None of<br \/>\nthem frees or queues the skb, so on that path the caller still owns it.<\/p>\n<p>tcf_ct_act() however funnels every non-zero return into the<br \/>\nownership-transfer exit:<\/p>\n<p>\terr = tcf_ct_handle_fragments(net, skb, family, p-&gt;zone, &amp;defrag);<br \/>\n\tif (err)<br \/>\n\t\tgoto out_frag;<br \/>\n\t&#8230;<br \/>\nout_frag:<br \/>\n\tif (err != -EINPROGRESS)<br \/>\n\t\ttcf_action_inc_drop_qstats(&amp;c-&gt;common);<br \/>\n\treturn TC_ACT_CONSUMED;<\/p>\n<p>TC_ACT_CONSUMED means the action took ownership of the skb, so no caller<br \/>\nfrees it &#8211; sch_handle_ingress(), sch_handle_egress() and<br \/>\ntcf_qevent_handle() all deliberately skip the free for that verdict. The<br \/>\nskb is therefore orphaned: one sk_buff plus its data buffer is leaked per<br \/>\nmalformed packet, unbounded. Note the drop counter is already incremented<br \/>\nfor these errors, so the statistics claim a drop that never happens.<\/p>\n<p>Three different ownership states reach out_frag: today &#8211; the skb may be<br \/>\nqueued by the defrag engine (-EINPROGRESS), already freed by<br \/>\nnf_ct_handle_fragments(), or still owned by us. Tell the caller which of<br \/>\nthose it is, and free the packet ourselves in the last case, which<br \/>\nrestores the TC_ACT_SHOT behaviour that predated the Fixes: commit.<\/p>\n<p>Reproduced on v7.2-rc6 with a 54-byte frame carrying a 40-byte IPv6<br \/>\nheader with nexthdr = 0 (hop-by-hop) and nothing after it, on a<br \/>\nclsact ingress chain with &#8220;action ct&#8221;. kmemleak reports one leaked<br \/>\n232-byte skbuff_head_cache object plus its 704-byte data buffer per<br \/>\npacket; with this patch it reports none.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>net\/sched: act_ct: fix sk_buff leak when the header checks reject a packet<\/p>\n<p>tcf_ct_handle_fragments() runs its header sanity checks<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-11224","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/11224","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=11224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}