Commit d3488480 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

nfp: bpf: allow stack accesses via modified stack registers

As long as the verifier tells us the stack offset exactly we
can render the LMEM reads quite easily.  Simply make sure that
the offset is constant for a given instruction and add it to
the instruction's offset.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9a90c83c
......@@ -771,9 +771,10 @@ wrp_lmem_store(struct nfp_prog *nfp_prog, u8 src, u8 src_byte, s32 off,
static int
mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
unsigned int size, u8 gpr, bool clr_gpr, lmem_step step)
unsigned int size, unsigned int ptr_off, u8 gpr, bool clr_gpr,
lmem_step step)
{
s32 off = nfp_prog->stack_depth + meta->insn.off;
s32 off = nfp_prog->stack_depth + meta->insn.off + ptr_off;
bool first = true, last;
u8 prev_gpr = 255;
u32 gpr_byte = 0;
......@@ -1311,10 +1312,10 @@ static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int
mem_ldx_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
unsigned int size)
unsigned int size, unsigned int ptr_off)
{
return mem_op_stack(nfp_prog, meta, size, meta->insn.dst_reg * 2, true,
wrp_lmem_load);
return mem_op_stack(nfp_prog, meta, size, ptr_off,
meta->insn.dst_reg * 2, true, wrp_lmem_load);
}
static int mem_ldx_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
......@@ -1401,7 +1402,8 @@ mem_ldx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
return mem_ldx_data(nfp_prog, meta, size);
if (meta->ptr.type == PTR_TO_STACK)
return mem_ldx_stack(nfp_prog, meta, size);
return mem_ldx_stack(nfp_prog, meta, size,
meta->ptr.off + meta->ptr.var_off.value);
return -EOPNOTSUPP;
}
......@@ -1482,10 +1484,10 @@ mem_stx_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
static int
mem_stx_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
unsigned int size)
unsigned int size, unsigned int ptr_off)
{
return mem_op_stack(nfp_prog, meta, size, meta->insn.src_reg * 2, false,
wrp_lmem_store);
return mem_op_stack(nfp_prog, meta, size, ptr_off,
meta->insn.src_reg * 2, false, wrp_lmem_store);
}
static int
......@@ -1496,7 +1498,8 @@ mem_stx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
return mem_stx_data(nfp_prog, meta, size);
if (meta->ptr.type == PTR_TO_STACK)
return mem_stx_stack(nfp_prog, meta, size);
return mem_stx_stack(nfp_prog, meta, size,
meta->ptr.off + meta->ptr.var_off.value);
return -EOPNOTSUPP;
}
......
......@@ -56,6 +56,7 @@ enum br_special {
enum static_regs {
STATIC_REG_IMM = 21, /* Bank AB */
STATIC_REG_STACK = 22, /* Bank A */
STATIC_REG_PKT_LEN = 22, /* Bank B */
};
......@@ -74,6 +75,8 @@ enum nfp_bpf_action_type {
#define pv_len(np) reg_lm(1, PKT_VEC_PKT_LEN)
#define pv_ctm_ptr(np) reg_lm(1, PKT_VEC_PKT_PTR)
#define stack_reg(np) reg_a(STATIC_REG_STACK)
#define stack_imm(np) imm_b(np)
#define plen_reg(np) reg_b(STATIC_REG_PKT_LEN)
#define pptr_reg(np) pv_ctm_ptr(np)
#define imm_a(np) reg_a(STATIC_REG_IMM)
......
......@@ -111,19 +111,29 @@ nfp_bpf_check_exit(struct nfp_prog *nfp_prog,
return 0;
}
static int nfp_bpf_check_stack_access(const struct bpf_reg_state *reg)
static int
nfp_bpf_check_stack_access(struct nfp_insn_meta *meta,
const struct bpf_reg_state *reg)
{
s32 old_off, new_off;
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;
}
if (meta->ptr.type == NOT_INIT)
return 0;
old_off = meta->ptr.off + meta->ptr.var_off.value;
new_off = reg->off + reg->var_off.value;
if (old_off == new_off)
return 0;
pr_info("stack access changed location was:%d is:%d\n",
old_off, new_off);
return -EINVAL;
}
static int
......@@ -141,7 +151,7 @@ nfp_bpf_check_ptr(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
}
if (reg->type == PTR_TO_STACK) {
err = nfp_bpf_check_stack_access(reg);
err = nfp_bpf_check_stack_access(meta, reg);
if (err)
return err;
}
......
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