Message ID | 20230421013406.33564-2-cengiz.can@canonical.com |
---|---|
State | New |
Headers | show |
Series | net: sched: Fix use after free in red_enqueue() | expand |
On 23/04/21 04:34AM, Cengiz Can wrote: > From: Dan Carpenter <dan.carpenter@oracle.com> > > BugLink: https://bugs.launchpad.net/bugs/2017013 > > We can't use "skb" again after passing it to qdisc_enqueue(). This is > basically identical to commit 2f09707d0c97 ("sch_sfb: Also store skb > len before calling child enqueue"). > > Fixes: d7f4f332f082 ("sch_red: update backlog as well") > Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> > Reviewed-by: Eric Dumazet <edumazet@google.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > (cherry picked from commit 8bdc2acd420c6f3dd1f1c78750ec989f02a1e2b9) > Signed-off-by: Cengiz Can <cengiz.can@canonical.com> Acked-by: Andrei Gherzan <andrei.gherzan@canonical.com> > --- > net/sched/sch_red.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c > index 40adf1f07a82..b310842b4225 100644 > --- a/net/sched/sch_red.c > +++ b/net/sched/sch_red.c > @@ -72,6 +72,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch, > { > struct red_sched_data *q = qdisc_priv(sch); > struct Qdisc *child = q->qdisc; > + unsigned int len; > int ret; > > q->vars.qavg = red_calc_qavg(&q->parms, > @@ -126,9 +127,10 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch, > break; > } > > + len = qdisc_pkt_len(skb); > ret = qdisc_enqueue(skb, child, to_free); > if (likely(ret == NET_XMIT_SUCCESS)) { > - qdisc_qstats_backlog_inc(sch, skb); > + sch->qstats.backlog += len; > sch->q.qlen++; > } else if (net_xmit_drop_count(ret)) { > q->stats.pdrop++; > -- > 2.37.2 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 40adf1f07a82..b310842b4225 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -72,6 +72,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch, { struct red_sched_data *q = qdisc_priv(sch); struct Qdisc *child = q->qdisc; + unsigned int len; int ret; q->vars.qavg = red_calc_qavg(&q->parms, @@ -126,9 +127,10 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch, break; } + len = qdisc_pkt_len(skb); ret = qdisc_enqueue(skb, child, to_free); if (likely(ret == NET_XMIT_SUCCESS)) { - qdisc_qstats_backlog_inc(sch, skb); + sch->qstats.backlog += len; sch->q.qlen++; } else if (net_xmit_drop_count(ret)) { q->stats.pdrop++;