summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorBryam Vargas <hexlabsecurity@proton.me>2026-06-25 04:51:19 -0500
committerJakub Kicinski <kuba@kernel.org>2026-06-26 18:52:26 -0700
commite056e1dfcddca877dd46d704e8ec9860cfc9ec44 (patch)
tree3b78318e29e4c859e802f0d51fa359b234a1abdc /net
parentf9ba47fce5932c15891c89c60e76dfaca919cb8d (diff)
downloadlinux-2.6-e056e1dfcddca877dd46d704e8ec9860cfc9ec44.tar.gz
linux-2.6-e056e1dfcddca877dd46d704e8ec9860cfc9ec44.zip
net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked
When taprio's software path peeks a non-work-conserving child qdisc, the child stashes the peeked skb in its gso_skb; taprio_dequeue_from_txq() then takes the packet with a direct child ->dequeue() call, which ignores that stash, orphans the peeked skb and desyncs the child's qlen/backlog. With a qfq child this re-enters the child on an emptied list and dereferences NULL, panicking the kernel from softirq on ordinary egress. Take the packet through qdisc_dequeue_peeked(), as sch_red and sch_sfb now do. The helper returns the child's stashed skb first and is a no-op when there is none, so a work-conserving child is unaffected and the gated path now consumes the skb whose length was charged to the budget. Fixes: 5a781ccbd19e ("tc: Add support for configuring the taprio scheduler") Cc: stable@vger.kernel.org Cc: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Reviewed-by: Victor Nogueira <victor@mojatatu.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Link: https://patch.msgid.link/20260625-b4-disp-31bcb279-v1-1-85c40b83c529@proton.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/sched/sch_taprio.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 558987d9b977..299234a5f0fe 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -749,7 +749,7 @@ static struct sk_buff *taprio_dequeue_from_txq(struct Qdisc *sch, int txq,
return NULL;
skip_peek_checks:
- skb = child->ops->dequeue(child);
+ skb = qdisc_dequeue_peeked(child);
if (unlikely(!skb))
return NULL;