net_sched: fix skb memory leak in deferred qdisc drops
Subsystems (2)
PATCH v2 1/1 net_sched: fix skb memory leak in deferred qdisc drops
When the network stack cleans up the deferred list via qdisc_run_end(), it operates on the root qdisc. If the root qdisc do not implement the TCQ_F_DEQUEUE_DROPS flag the packets queue to free are never freed and gets stranded on the child's local to_free list.
Fix this by making qdisc_dequeue_drop() aware of the root qdisc. It fetches the root qdisc and check for the TCQ_F_DEQUEUE_DROPS flag. If the flag is present, the packet is appended directly to the root's to_free list. Otherwise, drop it directly as it was done before the optimization was implemented.
---
v2: added RCU read lock protection around root pointer and used root qdisc to append the packets to free
--- include/net/sch_generic.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
include/net/sch_generic.h +13 -3
@@ -1170,12 +1170,22 @@ static inline void tcf_kfree_skb_list(struct sk_buff *skb)static inline void qdisc_dequeue_drop (struct Qdisc *q,struct sk_buff *skb,enum skb_drop_reason reason) { +struct Qdisc *root; +DEBUG_NET_WARN_ON_ONCE (!(q->flags &TCQ_F_DEQUEUE_DROPS ));DEBUG_NET_WARN_ON_ONCE (q->flags &TCQ_F_NOLOCK ); -tcf_set_drop_reason (skb, reason); - skb->next = q->to_free; - q->to_free = skb; +rcu_read_lock (); + root =qdisc_root_sleeping (q); + +if (root->flags &TCQ_F_DEQUEUE_DROPS ) { +tcf_set_drop_reason (skb, reason); + skb->next = root->to_free; + root->to_free = skb; + }else { +kfree_skb_reason (skb, reason); + } +rcu_read_unlock (); }/* Instead of calling kfree_skb() while root qdisc lock is held,
Signature · 1 line
2.53.0
Quoted 12 lines · Fernando Fernandez Mancera
When the network stack cleans up the deferred list via
qdisc_run_end(), it operates on the root qdisc. If the root qdisc do not implement theTCQ_F_DEQUEUE_DROPSflag the packets queue to free are never freed and gets stranded on the child's localto_freelist.Fix this by making
qdisc_dequeue_drop()aware of the root qdisc. It fetches the root qdisc and check for theTCQ_F_DEQUEUE_DROPSflag. If the flag is present, the packet is appended directly to the root'sto_freelist. Otherwise, drop it directly as it was done before the optimization was implemented.
Quoted 5 lines
Fixes a6efc273ab82 ("net_sched: use qdisc_dequeue_drop() in cake, codel, fq_codel")Reported-by Damilola Bello <[email protected]>Closes https://lore.kernel.org/netdev/CAPgFtOLaedBMU0f_BxV2bXftTJSmJr018Q5uozOo5vVo6b9tjw@mail.gmail.com/ open hereSigned-off-by Fernando Fernandez Mancera <[email protected]>---
Thanks !
This patch was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:
Quoted 5 lines · On Wed, 8 Apr 2026 12:00:44 +0200 you wrote:
When the network stack cleans up the deferred list via
qdisc_run_end(), it operates on the root qdisc. If the root qdisc do not implement theTCQ_F_DEQUEUE_DROPSflag the packets queue to free are never freed and gets stranded on the child's localto_freelist.
Quoted 7 lines
Fix this by making
qdisc_dequeue_drop()aware of the root qdisc. It fetches the root qdisc and check for theTCQ_F_DEQUEUE_DROPSflag. If the flag is present, the packet is appended directly to the root'sto_freelist. Otherwise, drop it directly as it was done before the optimization was implemented.[...]
Here is the summary with links:
- [net,v2] net_sched: fix skb memory leak in deferred qdisc drops
https://git.kernel.org/netdev/net/c/a6bd339dbb35
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html