* [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree
@ 2025-07-17 2:28 William Liu
2025-07-17 2:29 ` [PATCH net v2 2/2] selftests/tc-testing: Test htb_dequeue_tree with deactivation and row emptying William Liu
2025-07-17 15:00 ` [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: William Liu @ 2025-07-17 2:28 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, pabeni, kuba, savy, jiri, davem, edumazet,
horms, William Liu
htb_lookup_leaf has a BUG_ON that can trigger with the following:
tc qdisc del dev lo root
tc qdisc add dev lo root handle 1: htb default 1
tc class add dev lo parent 1: classid 1:1 htb rate 64bit
tc qdisc add dev lo parent 1:1 handle 2: netem
tc qdisc add dev lo parent 2:1 handle 3: blackhole
ping -I lo -c1 -W0.001 127.0.0.1
The root cause is the following:
1. htb_dequeue calls htb_dequeue_tree which calls the dequeue handler on
the selected leaf qdisc
2. netem_dequeue calls enqueue on the child qdisc
3. blackhole_enqueue drops the packet and returns a value that is not
just NET_XMIT_SUCCESS
4. Because of this, netem_dequeue calls qdisc_tree_reduce_backlog, and
since qlen is now 0, it calls htb_qlen_notify -> htb_deactivate ->
htb_deactiviate_prios -> htb_remove_class_from_row -> htb_safe_rb_erase
5. As this is the only class in the selected hprio rbtree,
__rb_change_child in __rb_erase_augmented sets the rb_root pointer to
NULL
6. Because blackhole_dequeue returns NULL, netem_dequeue returns NULL,
which causes htb_dequeue_tree to call htb_lookup_leaf with the same
hprio rbtree, and fail the BUG_ON
The function graph for this scenario is shown here:
0) | htb_enqueue() {
0) + 13.635 us | netem_enqueue();
0) 4.719 us | htb_activate_prios();
0) # 2249.199 us | }
0) | htb_dequeue() {
0) 2.355 us | htb_lookup_leaf();
0) | netem_dequeue() {
0) + 11.061 us | blackhole_enqueue();
0) | qdisc_tree_reduce_backlog() {
0) | qdisc_lookup_rcu() {
0) 1.873 us | qdisc_match_from_root();
0) 6.292 us | }
0) 1.894 us | htb_search();
0) | htb_qlen_notify() {
0) 2.655 us | htb_deactivate_prios();
0) 6.933 us | }
0) + 25.227 us | }
0) 1.983 us | blackhole_dequeue();
0) + 86.553 us | }
0) # 2932.761 us | qdisc_warn_nonwc();
0) | htb_lookup_leaf() {
0) | BUG_ON();
------------------------------------------
The full original bug report can be seen here [1].
We can fix this just by returning NULL instead of the BUG_ON,
as htb_dequeue_tree returns NULL when htb_lookup_leaf returns
NULL.
[1] https://lore.kernel.org/netdev/pF5XOOIim0IuEfhI-SOxTgRvNoDwuux7UHKnE_Y5-zVd4wmGvNk2ceHjKb8ORnzw0cGwfmVu42g9dL7XyJLf1NEzaztboTWcm0Ogxuojoeo=@willsroot.io/
Fixes: 512bb43eb542 ("pkt_sched: sch_htb: Optimize WARN_ONs in htb_dequeue_tree() etc.")
Signed-off-by: William Liu <will@willsroot.io>
Signed-off-by: Savino Dicanosa <savy@syst3mfailure.io>
---
net/sched/sch_htb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 14bf71f57057..c968ea763774 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -821,7 +821,9 @@ static struct htb_class *htb_lookup_leaf(struct htb_prio *hprio, const int prio)
u32 *pid;
} stk[TC_HTB_MAXDEPTH], *sp = stk;
- BUG_ON(!hprio->row.rb_node);
+ if (unlikely(!hprio->row.rb_node))
+ return NULL;
+
sp->root = hprio->row.rb_node;
sp->pptr = &hprio->ptr;
sp->pid = &hprio->last_ptr_id;
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH net v2 2/2] selftests/tc-testing: Test htb_dequeue_tree with deactivation and row emptying
2025-07-17 2:28 [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree William Liu
@ 2025-07-17 2:29 ` William Liu
2025-07-17 15:00 ` [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: William Liu @ 2025-07-17 2:29 UTC (permalink / raw)
To: netdev
Cc: jhs, xiyou.wangcong, pabeni, kuba, savy, jiri, davem, edumazet,
horms, William Liu
Ensure that any deactivation and row emptying that occurs
during htb_dequeue_tree does not cause a kernel panic.
This scenario originally triggered a kernel BUG_ON, and
we are checking for a graceful fail now.
Signed-off-by: William Liu <will@willsroot.io>
Signed-off-by: Savino Dicanosa <savy@syst3mfailure.io>
---
v1 -> v2:
- Moved test case to earlier in the file
---
.../tc-testing/tc-tests/infra/qdiscs.json | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
index 5c6851e8d311..c54adc9b3604 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
@@ -127,6 +127,32 @@
"$IP addr del 10.10.10.10/24 dev $DUMMY"
]
},
+ {
+ "id": "5456",
+ "name": "Test htb_dequeue_tree with deactivation and row emptying",
+ "category": [
+ "qdisc",
+ "htb"
+ ],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ "$IP link set dev $DUMMY up || true",
+ "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+ "$TC qdisc add dev $DUMMY root handle 1: htb default 1",
+ "$TC class add dev $DUMMY parent 1: classid 1:1 htb rate 64bit ",
+ "$TC qdisc add dev $DUMMY parent 1:1 handle 2: netem",
+ "$TC qdisc add dev $DUMMY parent 2:1 handle 3: blackhole"
+ ],
+ "cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.11.11",
+ "expExitCode": "1",
+ "verifyCmd": "$TC -j qdisc show dev $DUMMY",
+ "matchJSON": [],
+ "teardown": [
+ "$TC qdisc del dev $DUMMY root"
+ ]
+ },
{
"id": "c024",
"name": "Test TBF with SKBPRIO - catch qlen corner cases",
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree
2025-07-17 2:28 [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree William Liu
2025-07-17 2:29 ` [PATCH net v2 2/2] selftests/tc-testing: Test htb_dequeue_tree with deactivation and row emptying William Liu
@ 2025-07-17 15:00 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-07-17 15:00 UTC (permalink / raw)
To: William Liu
Cc: netdev, jhs, xiyou.wangcong, pabeni, kuba, savy, jiri, davem,
edumazet, horms
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 17 Jul 2025 02:28:38 +0000 you wrote:
> htb_lookup_leaf has a BUG_ON that can trigger with the following:
>
> tc qdisc del dev lo root
> tc qdisc add dev lo root handle 1: htb default 1
> tc class add dev lo parent 1: classid 1:1 htb rate 64bit
> tc qdisc add dev lo parent 1:1 handle 2: netem
> tc qdisc add dev lo parent 2:1 handle 3: blackhole
> ping -I lo -c1 -W0.001 127.0.0.1
>
> [...]
Here is the summary with links:
- [net,v2,1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree
https://git.kernel.org/netdev/net/c/0e1d5d9b5c59
- [net,v2,2/2] selftests/tc-testing: Test htb_dequeue_tree with deactivation and row emptying
https://git.kernel.org/netdev/net/c/88b06e4fb4bf
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-17 15:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-17 2:28 [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree William Liu
2025-07-17 2:29 ` [PATCH net v2 2/2] selftests/tc-testing: Test htb_dequeue_tree with deactivation and row emptying William Liu
2025-07-17 15:00 ` [PATCH net v2 1/2] net/sched: Return NULL when htb_lookup_leaf encounters an empty rbtree patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).