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

net/sched: cls_route: free emptied bucket on filter move

route4_change can move an existing filter to a different top-level
bucket: route4_set_parms recomputes the handle from TCA_ROUTE4_TO/
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
route4_delete to report *last=false even after the last live filter is
gone. That pins the empty tcf_proto 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 route4_delete
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:
CONFIG_NET_CLS_ROUTE4=y, CONFIG_NET_SCH_INGRESS=y, CONFIG_NET_CLS_ACT=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 '
Published: 2026-09-25
Score: n/a
EPSS: n/a
KEV: No
Impact: Memory Leak
Action: Patch
AI Analysis

Impact

The vulnerability arises when a traffic classification filter is moved to a different bucket. The route4_set_parms logic recomputes a handle that may differ, unlinking the filter from its original bucket but never freeing the now-empty bucket. This stale bucket remains in the head->table[] array, causing route4_delete to misreport a live filter and leave an empty tcf_proto object in memory. The unreferenced bucket creates a memory leak that can grow over time and lead to resource exhaustion.

Affected Systems

Affected systems include any Linux kernel built with the networking classifier route4 configuration: CONFIG_NET_CLS_ROUTE4=y, CONFIG_NET_SCH_INGRESS=y, CONFIG_NET_CLS_ACT=y. The issue manifests when administrative users use the 'tc' utility to add, change, or delete ingress filters on devices such as lo. Thus, all Linux environments that enable these networking features and allow privileged filter modifications are vulnerable.

Risk and Exploitability

Because the bug is triggered by 'tc' commands that require root privileges, the attack vector is local privilege escalation or for users already with kernel modification rights. EPSS is currently not available and the vulnerability is not in the CISA KEV list, indicating limited public exploitation. However, an unpatched kernel may accrue significant memory usage over time, ultimately impacting system availability. The CVSS score is not provided, but the potential for denial of service warrants prompt action.

Generated by OpenCVE AI on September 25, 2026 at 14:46 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Upgrade the Linux kernel to a version that includes the fix for CVE-2026-97959.
  • If an immediate kernel upgrade is not possible, disable CONFIG_NET_CLS_ROUTE4, or omit the clsact qdisc to prevent filter manipulation.
  • Restrict the use of the 'tc' command to trusted administrators and consider applying Linux capabilities or SELinux policies to limit filter configuration changes.

Generated by OpenCVE AI on September 25, 2026 at 14:46 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Fri, 25 Sep 2026 15:15:00 +0000

Type Values Removed Values Added
Weaknesses CWE-401

Fri, 25 Sep 2026 10:30:00 +0000

Type Values Removed Values Added
Description In the Linux kernel, the following vulnerability has been resolved: net/sched: cls_route: free emptied bucket on filter move route4_change can move an existing filter to a different top-level bucket: route4_set_parms recomputes the handle from TCA_ROUTE4_TO/ 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 route4_delete to report *last=false even after the last live filter is gone. That pins the empty tcf_proto 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 route4_delete 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: CONFIG_NET_CLS_ROUTE4=y, CONFIG_NET_SCH_INGRESS=y, CONFIG_NET_CLS_ACT=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 '
Title net/sched: cls_route: free emptied bucket on filter move
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-09-25T10:23:04.348Z

Reserved: 2026-09-25T10:18:58.205Z

Link: CVE-2026-97959

cve-icon Vulnrichment

No data.

cve-icon NVD

Status : Received

Published: 2026-09-25T11:17:23.600

Modified: 2026-09-25T11:17:23.600

Link: CVE-2026-97959

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-09-25T15:00:20Z

Weaknesses
  • CWE-401

    Missing Release of Memory after Effective Lifetime