Commit 1db817e7 authored by Cong Wang's avatar Cong Wang Committed by David S. Miller

net_sched: fix two more memory leaks in cls_tcindex

struct tcindex_filter_result contains two parts:
struct tcf_exts and struct tcf_result.

For the local variable 'cr', its exts part is never used but
initialized without being released properly on success path. So
just completely remove the exts part to fix this leak.

For the local variable 'new_filter_result', it is never properly
released if not used by 'r' on success path.

Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 033b228e
...@@ -304,9 +304,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -304,9 +304,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
struct nlattr *est, bool ovr, struct netlink_ext_ack *extack) struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
{ {
struct tcindex_filter_result new_filter_result, *old_r = r; struct tcindex_filter_result new_filter_result, *old_r = r;
struct tcindex_filter_result cr;
struct tcindex_data *cp = NULL, *oldp; struct tcindex_data *cp = NULL, *oldp;
struct tcindex_filter *f = NULL; /* make gcc behave */ struct tcindex_filter *f = NULL; /* make gcc behave */
struct tcf_result cr = {};
int err, balloc = 0; int err, balloc = 0;
struct tcf_exts e; struct tcf_exts e;
...@@ -345,13 +345,10 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -345,13 +345,10 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
cp->h = p->h; cp->h = p->h;
err = tcindex_filter_result_init(&new_filter_result); err = tcindex_filter_result_init(&new_filter_result);
if (err < 0)
goto errout1;
err = tcindex_filter_result_init(&cr);
if (err < 0) if (err < 0)
goto errout1; goto errout1;
if (old_r) if (old_r)
cr.res = r->res; cr = r->res;
if (tb[TCA_TCINDEX_HASH]) if (tb[TCA_TCINDEX_HASH])
cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
...@@ -442,8 +439,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -442,8 +439,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
} }
if (tb[TCA_TCINDEX_CLASSID]) { if (tb[TCA_TCINDEX_CLASSID]) {
cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]); cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
tcf_bind_filter(tp, &cr.res, base); tcf_bind_filter(tp, &cr, base);
} }
if (old_r && old_r != r) { if (old_r && old_r != r) {
...@@ -455,7 +452,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -455,7 +452,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
} }
oldp = p; oldp = p;
r->res = cr.res; r->res = cr;
tcf_exts_change(&r->exts, &e); tcf_exts_change(&r->exts, &e);
rcu_assign_pointer(tp->root, cp); rcu_assign_pointer(tp->root, cp);
...@@ -474,6 +471,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -474,6 +471,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
; /* nothing */ ; /* nothing */
rcu_assign_pointer(*fp, f); rcu_assign_pointer(*fp, f);
} else {
tcf_exts_destroy(&new_filter_result.exts);
} }
if (oldp) if (oldp)
...@@ -486,7 +485,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -486,7 +485,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
else if (balloc == 2) else if (balloc == 2)
kfree(cp->h); kfree(cp->h);
errout1: errout1:
tcf_exts_destroy(&cr.exts);
tcf_exts_destroy(&new_filter_result.exts); tcf_exts_destroy(&new_filter_result.exts);
errout: errout:
kfree(cp); kfree(cp);
......
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