linux/net/sched
Victor Nogueria 1e70274d3b net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked
[ Upstream commit 1b9bc71153 ]

When sfb has children (eg qfq qdisc) whose peek() callback is
qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
its child (sfb in this case), it will do the following:
 1a. do a peek() - and when sensing there's an skb the child can offer, then
     - the child in this case(sfb) calls its child's (qfq) peek.
        qfq does the right thing and will return the gso_skb queue packet.
        Note: if there wasnt a gso_skb entry then qfq will store it there.
 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
     - sfb will call the child's dequeue() which will essentially just
       try to grab something of qfq's queue.

[  127.594489][  T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
[  127.594741][  T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
[  127.595059][  T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[  127.595254][  T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
[  127.595461][  T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
[  127.596081][  T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
[  127.596337][  T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
[  127.596623][  T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
[  127.596917][  T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
[  127.597165][  T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
[  127.597404][  T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
[  127.597644][  T453] FS:  00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
[  127.597956][  T453] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  127.598160][  T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
[  127.598390][  T453] PKRU: 55555554
[  127.598509][  T453] Call Trace:
[  127.598629][  T453]  <TASK>
[  127.598718][  T453]  ? mark_held_locks+0x40/0x70
[  127.598890][  T453]  ? srso_alias_return_thunk+0x5/0xfbef5
[  127.599053][  T453]  sfb_dequeue+0x88/0x4d0
[  127.599174][  T453]  ? ktime_get+0x137/0x230
[  127.599328][  T453]  ? srso_alias_return_thunk+0x5/0xfbef5
[  127.599480][  T453]  ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
[  127.599670][  T453]  ? srso_alias_return_thunk+0x5/0xfbef5
[  127.599831][  T453]  tbf_dequeue+0x6b1/0x1098 [sch_tbf]
[  127.599988][  T453]  __qdisc_run+0x169/0x1900

The right thing to do in #1b is to grab the skb off gso_skb queue.
This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
method instead.

Fixes: e13e02a3c6 ("net_sched: SFB flow scheduler")
Signed-off-by: Victor Nogueria <victor@mojatatu.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260430152957.194015-3-jhs@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2026-06-19 13:33:22 +02:00
..
act_api.c net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc() 2024-07-05 09:14:30 +02:00
act_bpf.c bpf: Add bpf_prog_run_data_pointers() 2025-12-07 06:09:29 +09:00
act_connmark.c net/sched: act_connmark: handle errno on tcf_idr_check_alloc 2025-12-07 06:09:30 +09:00
act_csum.c net: sched: act_csum: validate nested VLAN headers 2026-06-01 17:35:02 +02:00
act_ct.c net/sched: act_ct: Only release RCU read lock after ct_ft 2026-06-01 17:35:29 +02:00
act_ctinfo.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_gact.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_gate.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_ife.c net/sched: act_ife: convert comma to semicolon 2026-02-06 16:42:05 +01:00
act_ipt.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_meta_mark.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
act_meta_skbprio.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
act_meta_skbtcindex.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
act_mirred.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_mpls.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_nat.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_pedit.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_police.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_sample.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_simple.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_skbedit.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_skbmod.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_tunnel_key.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
act_vlan.c net: sched: act: move global static variable net_id to tc_action_ops 2025-12-07 06:09:28 +09:00
cls_api.c net: sched: cls_api: fix tc_chain_fill_node to initialize tcm_info to zero to prevent an info-leak 2026-04-18 10:33:30 +02:00
cls_basic.c net_sched: refactor TC action init API 2021-08-02 10:24:38 +01:00
cls_bpf.c bpf: Add bpf_prog_run_data_pointers() 2025-12-07 06:09:29 +09:00
cls_cgroup.c net_sched: refactor TC action init API 2021-08-02 10:24:38 +01:00
cls_flow.c net/sched: cls_flow: fix NULL pointer dereference on shared blocks 2026-04-18 10:33:31 +02:00
cls_flower.c net: fix geneve_opt length integer overflow 2025-04-10 14:32:05 +02:00
cls_fw.c net/sched: cls_fw: fix NULL dereference of "old" filters before change() 2026-06-19 13:33:22 +02:00
cls_matchall.c net_sched: refactor TC action init API 2021-08-02 10:24:38 +01:00
cls_route.c net/sched: cls_route: No longer copy tcf_result on update to avoid use-after-free 2023-08-11 15:13:52 +02:00
cls_u32.c net/sched: cls_u32: use skb_header_pointer_careful() 2026-06-01 17:35:09 +02:00
em_canid.c net: sched: kerneldoc fixes 2020-07-13 17:20:40 -07:00
em_cmp.c net: sched: fix misspellings using misspell-fixer tool 2020-11-10 17:00:28 -08:00
em_ipset.c sched: consistently handle layer3 header accesses in the presence of VLANs 2020-07-03 14:34:53 -07:00
em_ipt.c sched: consistently handle layer3 header accesses in the presence of VLANs 2020-07-03 14:34:53 -07:00
em_meta.c sched: consistently handle layer3 header accesses in the presence of VLANs 2020-07-03 14:34:53 -07:00
em_nbyte.c net: sched: Return the correct errno code 2021-02-06 11:15:28 -08:00
em_text.c net: sched: em_text: fix possible memory leak in em_text_destroy() 2024-01-15 18:51:12 +01:00
em_u32.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152 2019-05-30 11:26:32 -07:00
ematch.c net_sched: reject TCF_EM_SIMPLE case for complex ematch module 2022-12-31 13:14:39 +01:00
Kconfig net/sched: Retire dsmark qdisc 2024-03-01 13:21:42 +01:00
Makefile net/sched: Retire dsmark qdisc 2024-03-01 13:21:42 +01:00
sch_api.c net/sched: sch_qfq: Fix null-deref in agg_dequeue 2025-12-07 06:09:12 +09:00
sch_blackhole.c Revert "net: sched: Pass root lock to Qdisc_ops.enqueue" 2020-07-16 16:48:34 -07:00
sch_cake.c net/sched: sch_cake: annotate data-races in cake_dump_stats() (V) 2026-06-01 17:35:43 +02:00
sch_cbs.c net/sched: cbs: Fix integer overflow in cbs_set_port_rate() 2024-12-14 19:51:36 +01:00
sch_choke.c net/sched: sch_choke: annotate data-races in choke_dump_stats() 2026-06-01 17:35:42 +02:00
sch_codel.c codel: remove sch->q.qlen check before qdisc_tree_reduce_backlog() 2025-08-28 16:24:33 +02:00
sch_drr.c sch_drr: make drr_qlen_notify() idempotent 2025-08-28 16:24:33 +02:00
sch_etf.c net: sched: delete duplicate cleanup of backlog and qlen 2022-10-29 10:12:57 +02:00
sch_ets.c net/sched: ets: fix divide by zero in the offload path 2026-04-18 10:33:09 +02:00
sch_fifo.c pfifo_tail_enqueue: Drop new packet when sch->limit == 0 2025-03-13 12:51:00 +01:00
sch_fq.c net_sched: Flush gso_skb list too during ->change() 2025-05-22 14:08:22 +02:00
sch_fq_codel.c net/sched: sch_fq_codel: remove data-races from fq_codel_dump_stats() 2026-06-01 17:35:40 +02:00
sch_fq_pie.c net/sched: sch_fq_pie: annotate data-races in fq_pie_dump_stats() 2026-06-01 17:35:42 +02:00
sch_frag.c net/sched: Extend qdisc control block with tc control block 2022-01-05 12:42:33 +01:00
sch_generic.c net_sched: limit try_bulk_dequeue_skb() batches 2025-12-07 06:09:28 +09:00
sch_gred.c net: sched: gred/red: remove unused variables in struct red_stats 2026-06-01 17:35:40 +02:00
sch_hfsc.c net/sched: sch_hfsc: fix divide-by-zero in rtsc_min() 2026-04-18 10:33:29 +02:00
sch_hhf.c net_sched: sch_hhf: annotate data-races in hhf_dump_stats() 2026-06-01 17:35:40 +02:00
sch_htb.c net/sched: Remove unnecessary WARNING condition for empty child qdisc in htb_activate 2025-08-28 16:24:38 +02:00
sch_ingress.c net/sched: Reserve TC_H_INGRESS (TC_H_CLSACT) for ingress (clsact) Qdiscs 2023-06-09 10:32:17 +02:00
sch_mq.c net: sched: update default qdisc visibility after Tx queue cnt changes 2021-11-18 19:16:10 +01:00
sch_mqprio.c net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64 2023-08-03 10:22:36 +02:00
sch_multiq.c net: sched: sch_multiq: fix possible OOB write in multiq_tune() 2024-07-05 09:14:06 +02:00
sch_netem.c net/sched: netem: validate slot configuration 2026-06-01 17:35:42 +02:00
sch_pie.c net/sched: sch_pie: annotate more data-races in pie_dump_stats() 2026-06-01 17:35:44 +02:00
sch_plug.c net: sched: sch_qfq: Fix UAF in qfq_dequeue() 2023-09-19 12:22:59 +02:00
sch_prio.c net_sched: prio: fix a race in prio_tune() 2025-06-27 11:05:20 +01:00
sch_qfq.c net/sched: qfq: Use cl_is_active to determine whether class is active in qfq_rm_from_ag 2026-02-06 16:41:53 +01:00
sch_red.c net/sched: sch_red: annotate data-races in red_dump_stats() 2026-06-01 17:35:40 +02:00
sch_sfb.c net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked 2026-06-19 13:33:22 +02:00
sch_sfq.c net_sched: sch_sfq: reject invalid perturb period 2025-06-27 11:05:37 +01:00
sch_skbprio.c net_sched: skbprio: Remove overly strict queue assertions 2025-04-10 14:32:04 +02:00
sch_taprio.c net/sched: taprio: fix use-after-free in advance_sched() on schedule switch 2026-06-01 17:35:38 +02:00
sch_tbf.c net_sched: tbf: fix a race in tbf_change() 2025-06-27 11:05:20 +01:00
sch_teql.c net/sched: teql: fix NULL pointer dereference in iptunnel_xmit on TEQL slave xmit 2026-04-18 10:33:12 +02:00