Commit e38cf366 authored by David S. Miller's avatar David S. Miller

Merge branch 'qdisc-null-deref'

Zhengchao Shao says:

====================
net: fix null pointer access issue in qdisc

These three patches fix the same type of problem. Set the default qdisc,
and then construct an init failure scenario when the dev qdisc is
configured on mqprio to trigger the reset process. NULL pointer access
may occur during the reset process.

---
v2: for fq_codel, revert the patch
---
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7b55c2ed 2a3fc782
...@@ -2224,8 +2224,12 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) ...@@ -2224,8 +2224,12 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch)
static void cake_reset(struct Qdisc *sch) static void cake_reset(struct Qdisc *sch)
{ {
struct cake_sched_data *q = qdisc_priv(sch);
u32 c; u32 c;
if (!q->tins)
return;
for (c = 0; c < CAKE_MAX_TINS; c++) for (c = 0; c < CAKE_MAX_TINS; c++)
cake_clear_tin(sch, c); cake_clear_tin(sch, c);
} }
......
...@@ -478,24 +478,26 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, ...@@ -478,24 +478,26 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
if (opt) { if (opt) {
err = fq_codel_change(sch, opt, extack); err = fq_codel_change(sch, opt, extack);
if (err) if (err)
return err; goto init_failure;
} }
err = tcf_block_get(&q->block, &q->filter_list, sch, extack); err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err) if (err)
return err; goto init_failure;
if (!q->flows) { if (!q->flows) {
q->flows = kvcalloc(q->flows_cnt, q->flows = kvcalloc(q->flows_cnt,
sizeof(struct fq_codel_flow), sizeof(struct fq_codel_flow),
GFP_KERNEL); GFP_KERNEL);
if (!q->flows) if (!q->flows) {
return -ENOMEM; err = -ENOMEM;
goto init_failure;
}
q->backlogs = kvcalloc(q->flows_cnt, sizeof(u32), GFP_KERNEL); q->backlogs = kvcalloc(q->flows_cnt, sizeof(u32), GFP_KERNEL);
if (!q->backlogs) if (!q->backlogs) {
return -ENOMEM; err = -ENOMEM;
goto alloc_failure;
}
for (i = 0; i < q->flows_cnt; i++) { for (i = 0; i < q->flows_cnt; i++) {
struct fq_codel_flow *flow = q->flows + i; struct fq_codel_flow *flow = q->flows + i;
...@@ -508,6 +510,13 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, ...@@ -508,6 +510,13 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
else else
sch->flags &= ~TCQ_F_CAN_BYPASS; sch->flags &= ~TCQ_F_CAN_BYPASS;
return 0; return 0;
alloc_failure:
kvfree(q->flows);
q->flows = NULL;
init_failure:
q->flows_cnt = 0;
return err;
} }
static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb) static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
......
...@@ -455,7 +455,8 @@ static void sfb_reset(struct Qdisc *sch) ...@@ -455,7 +455,8 @@ static void sfb_reset(struct Qdisc *sch)
{ {
struct sfb_sched_data *q = qdisc_priv(sch); struct sfb_sched_data *q = qdisc_priv(sch);
qdisc_reset(q->qdisc); if (likely(q->qdisc))
qdisc_reset(q->qdisc);
q->slot = 0; q->slot = 0;
q->double_buffering = false; q->double_buffering = false;
sfb_zero_all_buckets(q); sfb_zero_all_buckets(q);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment