diff options
author | Pedro Tammela <pctammela@mojatatu.com> | 2023-04-21 18:25:15 -0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-04-23 18:35:27 +0100 |
commit | e1201bc781c28766720e78a5e099ffa568be4d74 (patch) | |
tree | 7e001fca77ef6a51ba86a4e944521b1291807452 /net/sched | |
parent | 0c83c5210e18763ec54252b990d270748c99b01d (diff) | |
download | linux-stable-e1201bc781c28766720e78a5e099ffa568be4d74.tar.gz linux-stable-e1201bc781c28766720e78a5e099ffa568be4d74.tar.bz2 linux-stable-e1201bc781c28766720e78a5e099ffa568be4d74.zip |
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>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/act_pedit.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 24976cd4e4a2..cc4dfb01c6c7 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -251,8 +251,16 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, memcpy(nparms->tcfp_keys, parm->keys, ksize); for (i = 0; i < nparms->tcfp_nkeys; ++i) { + u32 offmask = nparms->tcfp_keys[i].offmask; 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 */ nparms->tcfp_keys[i].shift = min_t(size_t, 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 * 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 */ nparms->tcfp_off_max_hint = @@ -411,12 +419,12 @@ TC_INDIRECT_SCOPE int tcf_pedit_act(struct sk_buff *skb, sizeof(_d), &_d); if (!d) goto bad; - offset += (*d & tkey->offmask) >> tkey->shift; - } - if (offset % 4) { - pr_info("tc action pedit offset must be on 32 bit boundaries\n"); - goto bad; + offset += (*d & tkey->offmask) >> tkey->shift; + if (offset % 4) { + pr_info("tc action pedit offset must be on 32 bit boundaries\n"); + goto bad; + } } if (!offset_valid(skb, hoffset + offset)) { |