aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2017-10-23 11:58:08 -0700
committerDavid S. Miller <davem@davemloft.net>2017-10-24 17:38:37 +0900
commitee9133a845fe8ad15f989e29bf8e2c8abe7986b8 (patch)
tree29ac3ba321bf9bb5cccb95ad4fbe55e8eddd6cce /drivers/net/ethernet/netronome/nfp/bpf/verifier.c
parentnfp: bpf: refactor nfp_bpf_check_ptr() (diff)
downloadlinux-dev-ee9133a845fe8ad15f989e29bf8e2c8abe7986b8.tar.xz
linux-dev-ee9133a845fe8ad15f989e29bf8e2c8abe7986b8.zip
nfp: bpf: add stack write support
Stack is implemented by the LMEM register file. Unaligned accesses to LMEM are not allowed. Accesses also have to be 4B wide. To support stack we need to make sure offsets of pointers are known at translation time (for now) and perform correct load/mask/shift operations. Since we can access first 64B of LMEM without much effort support only stacks not bigger than 64B. Following commits will extend the possible sizes beyond that. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/verifier.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
index 4d2ed84a82e0..376d9938b823 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
@@ -111,18 +111,41 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog,
return 0;
}
+static int nfp_bpf_check_stack_access(const struct bpf_reg_state *reg)
+{
+ if (!tnum_is_const(reg->var_off)) {
+ pr_info("variable ptr stack access\n");
+ return -EINVAL;
+ }
+
+ if (reg->var_off.value || reg->off) {
+ pr_info("stack access via modified register\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int
nfp_bpf_check_ptr(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
const struct bpf_verifier_env *env, u8 reg_no)
{
const struct bpf_reg_state *reg = &env->cur_state.regs[reg_no];
+ int err;
if (reg->type != PTR_TO_CTX &&
+ reg->type != PTR_TO_STACK &&
reg->type != PTR_TO_PACKET) {
pr_info("unsupported ptr type: %d\n", reg->type);
return -EINVAL;
}
+ if (reg->type == PTR_TO_STACK) {
+ err = nfp_bpf_check_stack_access(reg);
+ if (err)
+ return err;
+ }
+
if (meta->ptr.type != NOT_INIT && meta->ptr.type != reg->type) {
pr_info("ptr type changed for instruction %d -> %d\n",
meta->ptr.type, reg->type);
@@ -143,11 +166,6 @@ nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx, int prev_insn_idx)
meta = nfp_bpf_goto_meta(priv->prog, meta, insn_idx, env->prog->len);
priv->meta = meta;
- if (meta->insn.src_reg == BPF_REG_10 ||
- meta->insn.dst_reg == BPF_REG_10) {
- pr_err("stack not yet supported\n");
- return -EINVAL;
- }
if (meta->insn.src_reg >= MAX_BPF_REG ||
meta->insn.dst_reg >= MAX_BPF_REG) {
pr_err("program uses extended registers - jit hardening?\n");
@@ -176,6 +194,8 @@ int nfp_prog_verify(struct nfp_prog *nfp_prog, struct bpf_prog *prog)
struct nfp_bpf_analyzer_priv *priv;
int ret;
+ nfp_prog->stack_depth = prog->aux->stack_depth;
+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;