net/sched: sch_taprio: fix possible use-after-free
[platform/kernel/linux-rpi.git] / net / sched / sch_taprio.c
index bb424f6..a76a2af 100644 (file)
@@ -1632,13 +1632,13 @@ static void taprio_reset(struct Qdisc *sch)
        int i;
 
        hrtimer_cancel(&q->advance_timer);
+       qdisc_synchronize(sch);
+
        if (q->qdiscs) {
                for (i = 0; i < dev->num_tx_queues; i++)
                        if (q->qdiscs[i])
                                qdisc_reset(q->qdiscs[i]);
        }
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void taprio_destroy(struct Qdisc *sch)
@@ -1655,6 +1655,7 @@ static void taprio_destroy(struct Qdisc *sch)
         * happens in qdisc_create(), after taprio_init() has been called.
         */
        hrtimer_cancel(&q->advance_timer);
+       qdisc_synchronize(sch);
 
        taprio_disable_offload(dev, q, NULL);
 
@@ -1950,12 +1951,14 @@ start_error:
 
 static struct Qdisc *taprio_leaf(struct Qdisc *sch, unsigned long cl)
 {
-       struct netdev_queue *dev_queue = taprio_queue_get(sch, cl);
+       struct taprio_sched *q = qdisc_priv(sch);
+       struct net_device *dev = qdisc_dev(sch);
+       unsigned int ntx = cl - 1;
 
-       if (!dev_queue)
+       if (ntx >= dev->num_tx_queues)
                return NULL;
 
-       return dev_queue->qdisc_sleeping;
+       return q->qdiscs[ntx];
 }
 
 static unsigned long taprio_find(struct Qdisc *sch, u32 classid)