Commit e1201bc7 authored by Pedro Tammela's avatar Pedro Tammela Committed by David S. Miller

net/sched: act_pedit: check static offsets a priori

Static key offsets should always be on 32 bit boundaries. Validate them on
create/update time for static offsets and move the datapath validation
for runtime offsets only.

iproute2 already errors out if a given offset and data size cannot be
packed to a 32 bit boundary. This change will make sure users which
create/update pedit instances directly via netlink also error out,
instead of finding out when packets are traversing.
Reviewed-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarPedro Tammela <pctammela@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0c83c521
...@@ -251,8 +251,16 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -251,8 +251,16 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
memcpy(nparms->tcfp_keys, parm->keys, ksize); memcpy(nparms->tcfp_keys, parm->keys, ksize);
for (i = 0; i < nparms->tcfp_nkeys; ++i) { for (i = 0; i < nparms->tcfp_nkeys; ++i) {
u32 offmask = nparms->tcfp_keys[i].offmask;
u32 cur = nparms->tcfp_keys[i].off; u32 cur = nparms->tcfp_keys[i].off;
/* The AT option can be added to static offsets in the datapath */
if (!offmask && cur % 4) {
NL_SET_ERR_MSG_MOD(extack, "Offsets must be on 32bit boundaries");
ret = -EINVAL;
goto put_chain;
}
/* sanitize the shift value for any later use */ /* sanitize the shift value for any later use */
nparms->tcfp_keys[i].shift = min_t(size_t, nparms->tcfp_keys[i].shift = min_t(size_t,
BITS_PER_TYPE(int) - 1, BITS_PER_TYPE(int) - 1,
...@@ -261,7 +269,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -261,7 +269,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
/* The AT option can read a single byte, we can bound the actual /* The AT option can read a single byte, we can bound the actual
* value with uchar max. * value with uchar max.
*/ */
cur += (0xff & nparms->tcfp_keys[i].offmask) >> nparms->tcfp_keys[i].shift; cur += (0xff & offmask) >> nparms->tcfp_keys[i].shift;
/* Each key touches 4 bytes starting from the computed offset */ /* Each key touches 4 bytes starting from the computed offset */
nparms->tcfp_off_max_hint = nparms->tcfp_off_max_hint =
...@@ -411,12 +419,12 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb, ...@@ -411,12 +419,12 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb,
sizeof(_d), &_d); sizeof(_d), &_d);
if (!d) if (!d)
goto bad; goto bad;
offset += (*d & tkey->offmask) >> tkey->shift;
}
if (offset % 4) { offset += (*d & tkey->offmask) >> tkey->shift;
pr_info("tc action pedit offset must be on 32 bit boundaries\n"); if (offset % 4) {
goto bad; pr_info("tc action pedit offset must be on 32 bit boundaries\n");
goto bad;
}
} }
if (!offset_valid(skb, hoffset + offset)) { if (!offset_valid(skb, hoffset + offset)) {
......
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