Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30e99ed6 authored by Wei Yongjun's avatar Wei Yongjun Committed by David S. Miller
Browse files

net: sched: act_pedit: fix possible memory leak in tcf_pedit_init()



'keys_ex' is malloced by tcf_pedit_keys_ex_parse() in tcf_pedit_init()
but not all of the error handle path free it, this may cause memory
leak. This patch fix it.

Fixes: 71d0ed70 ("net/act_pedit: Support using offset relative to the conventional network headers")
Signed-off-by: default avatarWei Yongjun <weiyongjun1@huawei.com>
Acked-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7184e7e7
Loading
Loading
Loading
Loading
+16 −9
Original line number Original line Diff line number Diff line
@@ -175,32 +175,35 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
	if (!tcf_idr_check(tn, parm->index, a, bind)) {
	if (!tcf_idr_check(tn, parm->index, a, bind)) {
		if (!parm->nkeys) {
		if (!parm->nkeys) {
			NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
			NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed");
			return -EINVAL;
			ret = -EINVAL;
			goto out_free;
		}
		}
		ret = tcf_idr_create(tn, parm->index, est, a,
		ret = tcf_idr_create(tn, parm->index, est, a,
				     &act_pedit_ops, bind, false);
				     &act_pedit_ops, bind, false);
		if (ret)
		if (ret)
			return ret;
			goto out_free;
		p = to_pedit(*a);
		p = to_pedit(*a);
		keys = kmalloc(ksize, GFP_KERNEL);
		keys = kmalloc(ksize, GFP_KERNEL);
		if (!keys) {
		if (!keys) {
			tcf_idr_release(*a, bind);
			tcf_idr_release(*a, bind);
			kfree(keys_ex);
			ret = -ENOMEM;
			return -ENOMEM;
			goto out_free;
		}
		}
		ret = ACT_P_CREATED;
		ret = ACT_P_CREATED;
	} else {
	} else {
		if (bind)
		if (bind)
			return 0;
			goto out_free;
		tcf_idr_release(*a, bind);
		tcf_idr_release(*a, bind);
		if (!ovr)
		if (!ovr) {
			return -EEXIST;
			ret = -EEXIST;
			goto out_free;
		}
		p = to_pedit(*a);
		p = to_pedit(*a);
		if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
		if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
			keys = kmalloc(ksize, GFP_KERNEL);
			keys = kmalloc(ksize, GFP_KERNEL);
			if (!keys) {
			if (!keys) {
				kfree(keys_ex);
				ret = -ENOMEM;
				return -ENOMEM;
				goto out_free;
			}
			}
		}
		}
	}
	}
@@ -222,6 +225,10 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
	if (ret == ACT_P_CREATED)
	if (ret == ACT_P_CREATED)
		tcf_idr_insert(tn, *a);
		tcf_idr_insert(tn, *a);
	return ret;
	return ret;
out_free:
	kfree(keys_ex);
	return ret;

}
}


static void tcf_pedit_cleanup(struct tc_action *a)
static void tcf_pedit_cleanup(struct tc_action *a)