[BUG] net/sched: cls_fw failed add changes live filter state
From: shaos
Date: Thu Oct 22 2026 - 10:50:38 EST
Hello,
A rejected new-style filter add can leave a new fw_head and its request-supplied mask published in an existing legacy cls_fw chain. On Linux v7.3, an optionless legacy FW filter first creates the tcf_proto. A later add supplies a non-default mask and a nonexistent ingress device. The request returns -ENODEV, but the mask remains installed: a subsequent otherwise-valid default-mask add returns -EINVAL, while an add using the retained mask succeeds.
The same failed request also changes the existing datapath behavior. In the reproducer, packets previously classified into the configured prio class instead enter the default class after the rejected request. A clean control keeps classifying them into the configured class.
HEAD commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
git tree: 30fd2ef82912c26cf3a58ad0ba6afc375fa851ac
source version: Linux 7.3.0, local master
compiler: gcc 11.4.0, GNU ld 2.38
console output:
https://gist.githubusercontent.com/shaos26/031126b2aeea4add6fe9fb8c7d9f36f7/raw/038fc0766949ae6025e04308b63e3ad065a02e53/console-output.txt
kernel config:
https://gist.githubusercontent.com/shaos26/031126b2aeea4add6fe9fb8c7d9f36f7/raw/96fd3ada617c0f89dc344f7bb650b0818c480e65/kernel-config.txt
reproducer:
https://gist.githubusercontent.com/shaos26/031126b2aeea4add6fe9fb8c7d9f36f7/raw/c49340adda66fae59de716c352f915c8738e947b/poc.c
initramfs init:
https://gist.githubusercontent.com/shaos26/031126b2aeea4add6fe9fb8c7d9f36f7/raw/5dcb67be6b9905a0b466bc98dd73369ade7dc6e4/init
reproduction notes:
https://gist.githubusercontent.com/shaos26/031126b2aeea4add6fe9fb8c7d9f36f7/raw/fd147fa4b5dd1c4fa1b0831993137b1ff57f4529/reproduction.md
Build the tested kernel with the attached configuration. Build poc.c as a static binary at /poc, place it and the attached init in an initramfs as /poc and /init, then boot a disposable x86-64 QEMU guest with a serial console. The default mode reproduces the retained state; challenge_mode=datapath and challenge_mode=datapath-control exercise the packet-classification effect.
Impact and prerequisites:
A failed filter-add request can silently alter live classifier state and packet handling in that network namespace. The operation requires CAP_NET_ADMIN in the target network namespace. No privilege escalation or cross-namespace effect is demonstrated.
Validation: Two fresh positive boots reproduced the retained mask, close controls passed, the datapath positive/control showed the class change only after the failed request, and a scratch rollback kernel passed the fixed control.
Thanks,
shaos