Skip to content

Commit bf26ad9

Browse files
ffmanceragregkh
authored andcommitted
net_sched: fix skb memory leak in deferred qdisc drops
[ Upstream commit a6bd339 ] 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. Fixes: a6efc27 ("net_sched: use qdisc_dequeue_drop() in cake, codel, fq_codel") Reported-by: Damilola Bello <damilola@aterlo.com> Closes: https://lore.kernel.org/netdev/CAPgFtOLaedBMU0f_BxV2bXftTJSmJr018Q5uozOo5vVo6b9tjw@mail.gmail.com/ Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260408100044.4530-1-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 0ca564d commit bf26ad9

1 file changed

Lines changed: 13 additions & 3 deletions

File tree

include/net/sch_generic.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,12 +1170,22 @@ static inline void tcf_kfree_skb_list(struct sk_buff *skb)
11701170
static inline void qdisc_dequeue_drop(struct Qdisc *q, struct sk_buff *skb,
11711171
enum skb_drop_reason reason)
11721172
{
1173+
struct Qdisc *root;
1174+
11731175
DEBUG_NET_WARN_ON_ONCE(!(q->flags & TCQ_F_DEQUEUE_DROPS));
11741176
DEBUG_NET_WARN_ON_ONCE(q->flags & TCQ_F_NOLOCK);
11751177

1176-
tcf_set_drop_reason(skb, reason);
1177-
skb->next = q->to_free;
1178-
q->to_free = skb;
1178+
rcu_read_lock();
1179+
root = qdisc_root_sleeping(q);
1180+
1181+
if (root->flags & TCQ_F_DEQUEUE_DROPS) {
1182+
tcf_set_drop_reason(skb, reason);
1183+
skb->next = root->to_free;
1184+
root->to_free = skb;
1185+
} else {
1186+
kfree_skb_reason(skb, reason);
1187+
}
1188+
rcu_read_unlock();
11791189
}
11801190

11811191
/* Instead of calling kfree_skb() while root qdisc lock is held,

0 commit comments

Comments
 (0)