[BUG] net/sched: cls_u32 accepts skip_sw without hardware offload

From: shaos

Date: Thu Oct 22 2026 - 11:10:07 EST


Hello,

A software-only cls_u32 key-node filter is added with skip_sw and action drop. u32_change() passes the internal request flags instead of the parsed userflags to the key-node offload helper, so the filter is accepted, marked skip_sw not_in_hw, and skipped by software classification.

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/52214e44c4d45823a935cbd396412102/raw/aa356e9f13d5e6d7c721e69b35db0dbde2b97a38/console-output.txt
kernel config:
https://gist.githubusercontent.com/shaos26/52214e44c4d45823a935cbd396412102/raw/08cfe6b272327f21ad917ee22a487862bd57e280/kernel-config.txt
reproducer:
https://gist.githubusercontent.com/shaos26/52214e44c4d45823a935cbd396412102/raw/8087f854d32060878b4c9a50c4a80d357bd5c5ae/poc-init.sh
auxiliary reproducer (run-qemu.sh):
https://gist.githubusercontent.com/shaos26/52214e44c4d45823a935cbd396412102/raw/369242a1cc359378a8e841cb4373d447fc372ef2/run-qemu.sh
auxiliary reproducer (rebuild-initramfs.sh):
https://gist.githubusercontent.com/shaos26/52214e44c4d45823a935cbd396412102/raw/dfd743e0125beaef6d76fc1d7ed9ee2de67b6471/rebuild-initramfs.sh

Build the tested kernel with the attached configuration, then recreate the supplied minimal initramfs or use a test system with iproute2 tc. poc-init.sh runs the ordinary drop control, the skip_sw positive and a hash-node close control; run-qemu.sh is the archived guest launcher.

Impact and prerequisites:
A filter the administrator intended to require hardware offload is silently inactive, and matching traffic passes. The user must already hold CAP_NET_ADMIN in the namespace; this is a configuration/policy correctness bug, not a demonstrated boundary bypass against a different principal.

Validation: Two fresh exact-revision boots showed the skip_sw filter accepted and ping succeeding while the ordinary drop control blocked it. A two-line patched control rejected the filter with EOPNOTSUPP.

Thanks,

shaos