diff options
author | Hiroaki SHIMODA <shimoda.hiroaki@gmail.com> | 2014-02-26 07:43:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-27 12:53:50 -0500 |
commit | 724b9e1d75ab3401aaa081bd4efb440c1b3509db (patch) | |
tree | ad5545d23ed048dc2576eb8537446c3ccc421003 /net | |
parent | 09a89c219baf0f116387efc928e325cf23630f20 (diff) |
sch_tbf: Fix potential memory leak in tbf_change().
The allocated child qdisc is not freed in error conditions.
Defer the allocation after user configuration turns out to be
valid and acceptable.
Fixes: cc106e441a63b ("net: sched: tbf: fix the calculation of max_size")
Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Cc: Yang Yingliang <yangyingliang@huawei.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/sched/sch_tbf.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 1cb413fead89..4f505a006896 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -334,18 +334,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
334 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, | 334 | qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate, |
335 | tb[TCA_TBF_PTAB])); | 335 | tb[TCA_TBF_PTAB])); |
336 | 336 | ||
337 | if (q->qdisc != &noop_qdisc) { | ||
338 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
339 | if (err) | ||
340 | goto done; | ||
341 | } else if (qopt->limit > 0) { | ||
342 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | ||
343 | if (IS_ERR(child)) { | ||
344 | err = PTR_ERR(child); | ||
345 | goto done; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); | 337 | buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U); |
350 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); | 338 | mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U); |
351 | 339 | ||
@@ -390,6 +378,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
390 | goto done; | 378 | goto done; |
391 | } | 379 | } |
392 | 380 | ||
381 | if (q->qdisc != &noop_qdisc) { | ||
382 | err = fifo_set_limit(q->qdisc, qopt->limit); | ||
383 | if (err) | ||
384 | goto done; | ||
385 | } else if (qopt->limit > 0) { | ||
386 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit); | ||
387 | if (IS_ERR(child)) { | ||
388 | err = PTR_ERR(child); | ||
389 | goto done; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | sch_tree_lock(sch); | 393 | sch_tree_lock(sch); |
394 | if (child) { | 394 | if (child) { |
395 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); | 395 | qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); |