net/sched: act_simple: fix parsing of TCA_DEF_DATA
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>
This commit is contained in:
parent
6310a882fb
commit
8d499533e0
|
@ -53,22 +53,22 @@ static void tcf_simp_release(struct tc_action *a)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue