| From: Davide Caratti <dcaratti@redhat.com> |
| Date: Fri, 8 Jun 2018 05:02:31 +0200 |
| Subject: net/sched: act_simple: fix parsing of TCA_DEF_DATA |
| |
| commit 8d499533e0bc02d44283dbdab03142b599b8ba16 upstream. |
| |
| 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: fa1b1cff3d06 ("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> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| --- a/net/sched/act_simple.c |
| +++ b/net/sched/act_simple.c |
| @@ -52,22 +52,22 @@ static void tcf_simp_release(struct tc_a |
| 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); |
| if (unlikely(!d->tcfd_defdata)) |
| return -ENOMEM; |
| - strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); |
| + nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA); |
| 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) |
| { |
| spin_lock_bh(&d->tcf_lock); |
| d->tcf_action = p->action; |
| 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); |
| } |
| |
| @@ -83,7 +83,6 @@ static int tcf_simp_init(struct net *net |
| struct nlattr *tb[TCA_DEF_MAX + 1]; |
| struct tc_defact *parm; |
| struct tcf_defact *d; |
| - char *defdata; |
| int ret = 0, err; |
| |
| if (nla == NULL) |
| @@ -100,7 +99,6 @@ static int tcf_simp_init(struct net *net |
| return -EINVAL; |
| |
| parm = nla_data(tb[TCA_DEF_PARMS]); |
| - defdata = nla_data(tb[TCA_DEF_DATA]); |
| |
| if (!tcf_hash_check(parm->index, a, bind)) { |
| ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); |
| @@ -108,7 +106,7 @@ static int tcf_simp_init(struct net *net |
| return ret; |
| |
| d = to_defact(a); |
| - ret = alloc_defdata(d, defdata); |
| + ret = alloc_defdata(d, tb[TCA_DEF_DATA]); |
| if (ret < 0) { |
| tcf_hash_cleanup(a, est); |
| return ret; |
| @@ -124,7 +122,7 @@ static int tcf_simp_init(struct net *net |
| if (!ovr) |
| return -EEXIST; |
| |
| - reset_policy(d, defdata, parm); |
| + reset_policy(d, tb[TCA_DEF_DATA], parm); |
| } |
| |
| if (ret == ACT_P_CREATED) |