From: shaos <shawnq1@163.com>
To: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] net/sched: hfsc: clear eligible node on reset
Date: Wed, 4 Nov 2026 01:38:44 +0800 (CST) [thread overview]
Message-ID: <6AEA1C23.11E1A6.00008@m16.mail.163.com> (raw)
Hello,
hfsc_reset_class() clears the realtime class counters but leaves its
el_node marked as linked. hfsc_reset_qdisc() then discards the
scheduler-wide eligible tree by assigning RB_ROOT. After a link
reset with an RSC class backlogged, the next packet sees the stale
non-empty el_node, skips init_ed(), and leaves the class absent from the
new eligible tree. HFSC then retains the packet in its child qdisc
without a dequeue event or watchdog recovery.
Two fresh QEMU runs reproduced a permanently queued packet after
link down/up. An FSC-only class, a drained-queue reset, and a no-reset
control transmitted normally. A kernel with the patch below reported
RESULT=NOT_STUCK and transmitted the packet. This requires control of
the HFSC qdisc and is a scheduler liveness/correctness defect; no memory
corruption or privilege escalation was observed.
HEAD commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
Git tree: 30fd2ef82912c26cf3a58ad0ba6afc375fa851ac
Source version: Linux 7.3
Compiler: gcc 11.4.0, GNU ld 2.38
The console logs, full kernel config, packet sender, and QEMU/initramfs
harness are available from one fixed-revision Gist:
Console output:
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/console-output.txt
Kernel config:
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/kernel-config.txt
PoC source:
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/poc.c
Harness: hfsc_reset_harness.sh
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/hfsc_reset_harness.sh
Harness: init.sh
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/init.sh
Harness: mkinitramfs.sh
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/mkinitramfs.sh
Harness: run-qemu.sh
https://gist.githubusercontent.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268/raw/6344f32527074498da61f02b58068539859b388e/run-qemu.sh
Clone the Gist and build the vulnerable kernel and initramfs. The
kernel source is the HEAD commit above; use the attached full config.
The host needs gcc, fakeroot, cpio, gzip, BusyBox, iproute2, and QEMU:
git clone \
https://gist.github.com/shaos26/d7ec57d3a631368bd50ad0182ce9c268.git \
hfsc-repro
cd hfsc-repro
TMP=/tmp/hfsc-repro-build
mkdir -p "$TMP/rootfs"
git clone \
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git \
linux
git -C linux checkout c03c1a14507dfaf8b856c2608f9ac216021fc222
cp kernel-config.txt linux/.config
make -C linux olddefconfig
make -C linux -j"$(nproc)" bzImage
mkdir -p poc
mv hfsc_reset_harness.sh init.sh mkinitramfs.sh run-qemu.sh poc/
cc -O2 -static -Wall -Wextra -Werror -o poc/hfsc_probe poc.c
fakeroot -- sh poc/mkinitramfs.sh "$TMP/rootfs" "$TMP/initramfs.cpio.gz"
Run the positive and close controls on fresh QEMU boots:
KERNEL="$PWD/linux/arch/x86/boot/bzImage" \
INITRD="$TMP/initramfs.cpio.gz" OUT="$TMP/rt-reset.log" \
sh poc/run-qemu.sh rt-reset
KERNEL="$PWD/linux/arch/x86/boot/bzImage" \
INITRD="$TMP/initramfs.cpio.gz" OUT="$TMP/ls-reset.log" \
sh poc/run-qemu.sh ls-reset
KERNEL="$PWD/linux/arch/x86/boot/bzImage" \
INITRD="$TMP/initramfs.cpio.gz" OUT="$TMP/rt-drained-reset.log" \
sh poc/run-qemu.sh rt-drained-reset
KERNEL="$PWD/linux/arch/x86/boot/bzImage" \
INITRD="$TMP/initramfs.cpio.gz" OUT="$TMP/rt-noreset.log" \
sh poc/run-qemu.sh rt-noreset
The positive prints RESULT=STUCK. Controls print RESULT=CONTROL_PASS.
For the fixed-kernel mechanism control, rebuild from the patched source;
rt-reset then prints RESULT=NOT_STUCK. The guest configures a qdisc and
sends AF_PACKET frames, so it runs as root in QEMU. A direct trigger
requires CAP_NET_ADMIN and CAP_NET_RAW.
The eligible-node marker must be cleared when the class scheduler state
is reset:
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: shaos <shawnq1@163.com>
---
net/sched/sch_hfsc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1488,6 +1488,7 @@ static void hfsc_reset_class(struct hfsc_class *cl)
cl->cl_myf = 0;
cl->cl_cfmin = 0;
cl->cl_nactive = 0;
+ RB_CLEAR_NODE(&cl->el_node);
cl->vt_tree = RB_ROOT;
cl->cf_tree = RB_ROOT;
--
2.34.1
next reply other threads:[~2026-11-03 17:38 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 17:38 shaos [this message]
2026-11-03 17:44 ` netdev-bot+sinfo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6AEA1C23.11E1A6.00008@m16.mail.163.com \
--to=shawnq1@163.com \
--cc=jhs@mojatatu.com \
--cc=jiri@resnulli.us \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®