1
0
Fork 0

net/sched: act_simple: fix parsing of TCA_DEF_DATA

[ Upstream commit 8d499533e0 ]

use nla_strlcpy() to avoid copying data beyond the length of TCA_DEF_DATA
netlink attribute, in case it is less than SIMP_MAX_DATA and it does not
end with '\0' character.

v2: fix errors in the commit message, thanks Hangbin Liu

Fixes: fa1b1cff3d ("net_cls_act: Make act_simple use of netlink policy.")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
pull/10/head
Davide Caratti 2018-06-08 05:02:31 +02:00 committed by Greg Kroah-Hartman
parent 73c0eab8d2
commit 81d159444d
1 changed files with 6 additions and 9 deletions

View File

@ -53,22 +53,22 @@ static void tcf_simp_release(struct tc_action *a, int bind)
kfree(d->tcfd_defdata); kfree(d->tcfd_defdata);
} }
static int alloc_defdata(struct tcf_defact *d, char *defdata) static int alloc_defdata(struct tcf_defact *d, const struct nlattr *defdata)
{ {
d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL); d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL);
if (unlikely(!d->tcfd_defdata)) if (unlikely(!d->tcfd_defdata))
return -ENOMEM; return -ENOMEM;
strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
return 0; return 0;
} }
static void reset_policy(struct tcf_defact *d, char *defdata, static void reset_policy(struct tcf_defact *d, const struct nlattr *defdata,
struct tc_defact *p) struct tc_defact *p)
{ {
spin_lock_bh(&d->tcf_lock); spin_lock_bh(&d->tcf_lock);
d->tcf_action = p->action; d->tcf_action = p->action;
memset(d->tcfd_defdata, 0, SIMP_MAX_DATA); memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
spin_unlock_bh(&d->tcf_lock); spin_unlock_bh(&d->tcf_lock);
} }
@ -87,7 +87,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct tcf_defact *d; struct tcf_defact *d;
bool exists = false; bool exists = false;
int ret = 0, err; int ret = 0, err;
char *defdata;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
@ -110,8 +109,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return -EINVAL; return -EINVAL;
} }
defdata = nla_data(tb[TCA_DEF_DATA]);
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a, ret = tcf_idr_create(tn, parm->index, est, a,
&act_simp_ops, bind, false); &act_simp_ops, bind, false);
@ -119,7 +116,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return ret; return ret;
d = to_defact(*a); d = to_defact(*a);
ret = alloc_defdata(d, defdata); ret = alloc_defdata(d, tb[TCA_DEF_DATA]);
if (ret < 0) { if (ret < 0) {
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return ret; return ret;
@ -133,7 +130,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
reset_policy(d, defdata, parm); reset_policy(d, tb[TCA_DEF_DATA], parm);
} }
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)