Commit 185067a8 authored by Daniel Borkmann's avatar Daniel Borkmann

Merge branch 'bpf-max-pkt-offset'

Jiong Wang says:

====================
The maximum packet offset accessed by one BPF program is useful
information.

Because sometimes there could be packet split and it is possible for some
reasons (for example performance) we want to reject the BPF program if the
maximum packet size would trigger such split. Normally, MTU value is
treated as the maximum packet size, but one BPF program does not always
access the whole packet, it could only access the head portion of the data.

We could let verifier calculate the maximum packet offset ever used and
record it inside prog auxiliar information structure as a new field
"max_pkt_offset".
====================
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents bce6a149 cf599f50
...@@ -489,14 +489,15 @@ nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog, ...@@ -489,14 +489,15 @@ nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv; struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv;
unsigned int max_mtu, max_stack, max_prog_len; unsigned int fw_mtu, pkt_off, max_stack, max_prog_len;
dma_addr_t dma_addr; dma_addr_t dma_addr;
void *img; void *img;
int err; int err;
max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32; fw_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
if (max_mtu < nn->dp.netdev->mtu) { pkt_off = min(prog->aux->max_pkt_offset, nn->dp.netdev->mtu);
NL_SET_ERR_MSG_MOD(extack, "BPF offload not supported with MTU larger than HW packet split boundary"); if (fw_mtu < pkt_off) {
NL_SET_ERR_MSG_MOD(extack, "BPF offload not supported with potential packet access beyond HW packet split boundary");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -293,6 +293,7 @@ struct bpf_prog_aux { ...@@ -293,6 +293,7 @@ struct bpf_prog_aux {
atomic_t refcnt; atomic_t refcnt;
u32 used_map_cnt; u32 used_map_cnt;
u32 max_ctx_offset; u32 max_ctx_offset;
u32 max_pkt_offset;
u32 stack_depth; u32 stack_depth;
u32 id; u32 id;
u32 func_cnt; u32 func_cnt;
......
...@@ -1455,6 +1455,17 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off, ...@@ -1455,6 +1455,17 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off,
verbose(env, "R%d offset is outside of the packet\n", regno); verbose(env, "R%d offset is outside of the packet\n", regno);
return err; return err;
} }
/* __check_packet_access has made sure "off + size - 1" is within u16.
* reg->umax_value can't be bigger than MAX_PACKET_OFF which is 0xffff,
* otherwise find_good_pkt_pointers would have refused to set range info
* that __check_packet_access would have rejected this pkt access.
* Therefore, "off + reg->umax_value + size - 1" won't overflow u32.
*/
env->prog->aux->max_pkt_offset =
max_t(u32, env->prog->aux->max_pkt_offset,
off + reg->umax_value + size - 1);
return err; return err;
} }
...@@ -6138,6 +6149,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) ...@@ -6138,6 +6149,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
*/ */
prog->cb_access = 1; prog->cb_access = 1;
env->prog->aux->stack_depth = MAX_BPF_STACK; env->prog->aux->stack_depth = MAX_BPF_STACK;
env->prog->aux->max_pkt_offset = MAX_PACKET_OFF;
/* mark bpf_tail_call as different opcode to avoid /* mark bpf_tail_call as different opcode to avoid
* conditional branch in the interpeter for every normal * conditional branch in the interpeter for every normal
......
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