Mark instructions that use pointers to areas in the stack outside of the
current stack frame, and process them accordingly in mem_op_stack().
This way, we also support BPF-to-BPF calls where the caller passes a
pointer to data in its own stack frame to the callee (typically, when
the caller passes an address to one of its local variables located in
the stack, as an argument).

Thanks to Jakub and Jiong for figuring out how to deal with this case,
I just had to turn their email discussion into this patch.

Suggested-by: Jiong Wang <jiong.w...@netronome.com>
Suggested-by: Jakub Kicinski <jakub.kicin...@netronome.com>
Signed-off-by: Quentin Monnet <quentin.mon...@netronome.com>
Reviewed-by: Jiong Wang <jiong.w...@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicin...@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/bpf/jit.c      | 3 ++-
 drivers/net/ethernet/netronome/nfp/bpf/main.h     | 1 +
 drivers/net/ethernet/netronome/nfp/bpf/verifier.c | 3 +++
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c 
b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
index b393f9dea584..6ed1b5207ecd 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
@@ -1178,7 +1178,8 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct 
nfp_insn_meta *meta,
        bool lm3 = true;
        int ret;
 
-       if (meta->ptr_not_const) {
+       if (meta->ptr_not_const ||
+           meta->flags & FLAG_INSN_PTR_CALLER_STACK_FRAME) {
                /* Use of the last encountered ptr_off is OK, they all have
                 * the same alignment.  Depend on low bits of value being
                 * discarded when written to LMaddr register.
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h 
b/drivers/net/ethernet/netronome/nfp/bpf/main.h
index 44b787a0bd4b..25e10cfa2678 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -267,6 +267,7 @@ struct nfp_bpf_reg_state {
 
 #define FLAG_INSN_IS_JUMP_DST                  BIT(0)
 #define FLAG_INSN_IS_SUBPROG_START             BIT(1)
+#define FLAG_INSN_PTR_CALLER_STACK_FRAME       BIT(2)
 
 /**
  * struct nfp_insn_meta - BPF instruction wrapper
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c 
b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
index f31721bd1fac..cddb70786a58 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
@@ -336,6 +336,9 @@ nfp_bpf_check_stack_access(struct nfp_prog *nfp_prog,
 {
        s32 old_off, new_off;
 
+       if (reg->frameno != env->cur_state->curframe)
+               meta->flags |= FLAG_INSN_PTR_CALLER_STACK_FRAME;
+
        if (!tnum_is_const(reg->var_off)) {
                pr_vlog(env, "variable ptr stack access\n");
                return -EINVAL;
-- 
2.7.4

Reply via email to