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: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Simon Horman <simon.horman@corigine.com> Signed-off-by: Pedro Tammela <pctammela@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0c83c5210e
commit
e1201bc781
@ -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,
|
|||||||
/* 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,13 +419,13 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
offset += (*d & tkey->offmask) >> tkey->shift;
|
||||||
if (offset % 4) {
|
if (offset % 4) {
|
||||||
pr_info("tc action pedit offset must be on 32 bit boundaries\n");
|
pr_info("tc action pedit offset must be on 32 bit boundaries\n");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!offset_valid(skb, hoffset + offset)) {
|
if (!offset_valid(skb, hoffset + offset)) {
|
||||||
pr_info("tc action pedit offset %d out of bounds\n",
|
pr_info("tc action pedit offset %d out of bounds\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user