CVE-2026-97959: net/sched: cls_route: free emptied bucket on filter move
In the Linux kernel, the following vulnerability has been resolved:
net/sched: clsroute: free emptied bucket on filter move
route4change can move an existing filter to a different top-level bucket: route4setparms recomputes the handle from TCAROUTE4TO/ FROM/IIF, and the handle-mismatch check is gated on the 'new' flag, so for an existing filter the new handle may differ from the old one and land in a different bucket. When this happens, the filter is unlinked from the old bucket, but the bucket itself is never freed once it goes empty. The stale empty bucket remains in head->table[], causing route4delete to report last=false even after the last live filter is gone. That pins the empty tcfproto and causes a leak.
Fix this by refcounting the filters linked to a bucket and freeing the bucket when the count drops to zero. The existing scan in route4delete goes away with it.
The count is updated at all sites that link or unlink a filter during add, change and delete, and the bucket is dropped from head->table[] as soon as it reaches zero.
Conditions to recreate the bug: CONFIGNETCLSROUTE4=y, CONFIGNETSCHINGRESS=y, CONFIGNETCLSACT=y.
tc qdisc replace dev lo clsact tc filter add dev lo ingress protocol ip pref 100 route from 1 to 1 tc filter change dev lo ingress protocol ip pref 100 handle 0x10001 \ route from 1 to 2 tc filter del dev lo ingress protocol ip pref 100 handle 0x10002 \ route from 1 to 2 tc filter show dev lo ingress | grep -c 'pref 100 route chain 0 '
Affected Software
Event History
Frequently Asked Questions
Which systems are affected by this issue?
The issue requires the Linux kernel to be built with CONFIG_NET_CLS_ROUTE4=y, CONFIG_NET_SCH_INGRESS=y, and CONFIG_NET_CLS_ACT=y. It is triggered in configurations using route4 classifier filters attached through clsact/ingress scheduling.
What operation triggers the leak?
An existing route4 filter must be changed so that its TCA_ROUTE4_TO, TCA_ROUTE4_FROM, or TCA_ROUTE4_IIF parameters produce a different top-level bucket handle. The filter is removed from its old bucket, but the old bucket can remain allocated after becoming empty.
What is the practical impact?
An empty stale bucket can remain in the route4 classifier table and keep an otherwise empty tcf_proto pinned. This results in a resource leak when filters are moved between buckets and later removed.
How can I assess whether a system is exposed?
Check whether the kernel configuration enables all three required options and whether route4 filters are modified in a way that changes their top-level bucket. Systems that do not use the route4 classifier or do not perform such filter moves do not meet the described trigger conditions.