This means each entry in the parentage chain can have its insn identified,
 which will help to support bounded-loop handling later.

Signed-off-by: Edward Cree <ec...@solarflare.com>
---
 include/linux/bpf_verifier.h |  6 ++++--
 kernel/bpf/verifier.c        | 22 +++++++++++-----------
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 2b56be9dfb56..0bc49c768585 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -107,8 +107,10 @@ struct bpf_stack_state {
  */
 struct bpf_func_state {
        struct bpf_reg_state regs[MAX_BPF_REG];
-       /* index of call instruction that called into this func */
-       int callsite;
+       /* index of last instruction processed in this func.  In frames other
+        * than innermost, will be call insn
+        */
+       int insn_idx;
        /* stack frame number of this function state from pov of
         * enclosing bpf_verifier_state.
         * 0 = main function, 1 = first callee.
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index dfba9dbc5bfb..7a08b5e8e071 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -267,7 +267,7 @@ static void print_verifier_state(struct bpf_verifier_env 
*env,
                        /* reg->off should be 0 for SCALAR_VALUE */
                        verbose(env, "%lld", reg->var_off.value + reg->off);
                        if (t == PTR_TO_STACK)
-                               verbose(env, ",call_%d", func(env, 
reg)->callsite);
+                               verbose(env, ",frame_%u", reg->frameno);
                } else {
                        verbose(env, "(id=%d", reg->id);
                        if (t != SCALAR_VALUE)
@@ -711,12 +711,11 @@ static void init_reg_state(struct bpf_verifier_env *env,
        mark_reg_known_zero(env, regs, BPF_REG_1);
 }
 
-#define BPF_MAIN_FUNC (-1)
 static void init_func_state(struct bpf_verifier_env *env,
                            struct bpf_func_state *state,
-                           int callsite, int frameno, int subprogno)
+                           int entry, int frameno, int subprogno)
 {
-       state->callsite = callsite;
+       state->insn_idx = entry;
        state->frameno = frameno;
        state->subprogno = subprogno;
        init_reg_state(env, state);
@@ -2095,8 +2094,7 @@ static int check_func_call(struct bpf_verifier_env *env, 
struct bpf_insn *insn,
         * callee can read/write into caller's stack
         */
        init_func_state(env, callee,
-                       /* remember the callsite, it will be used by bpf_exit */
-                       *insn_idx /* callsite */,
+                       target /* entry point */,
                        state->curframe + 1 /* frameno within this callchain */,
                        subprog /* subprog number within this prog */);
 
@@ -2151,7 +2149,7 @@ static int prepare_func_exit(struct bpf_verifier_env 
*env, int *insn_idx)
        /* return to the caller whatever r0 had in the callee */
        caller->regs[BPF_REG_0] = *r0;
 
-       *insn_idx = callee->callsite + 1;
+       *insn_idx = caller->insn_idx + 1;
        if (env->log.level) {
                verbose(env, "returning from callee:\n");
                print_verifier_state(env, callee);
@@ -4232,7 +4230,7 @@ static bool states_equal(struct bpf_verifier_env *env,
         * and all frame states need to be equivalent
         */
        for (i = 0; i <= old->curframe; i++) {
-               if (old->frame[i]->callsite != cur->frame[i]->callsite)
+               if (old->frame[i]->insn_idx != cur->frame[i]->insn_idx)
                        return false;
                if (!func_states_equal(old->frame[i], cur->frame[i]))
                        return false;
@@ -4327,7 +4325,7 @@ static int is_state_visited(struct bpf_verifier_env *env, 
int insn_idx)
         * technically the current state is not proven to be safe yet,
         * but it will either reach outer most bpf_exit (which means it's safe)
         * or it will be rejected. Since there are no loops, we won't be
-        * seeing this tuple (frame[0].callsite, frame[1].callsite, .. insn_idx)
+        * seeing this tuple (frame[0].insn_idx, frame[1].insn_idx, .. insn_idx)
         * again on the way to bpf_exit
         */
        new_sl = kzalloc(sizeof(struct bpf_verifier_state_list), GFP_KERNEL);
@@ -4394,11 +4392,11 @@ static int do_check(struct bpf_verifier_env *env)
        mainprogno = add_subprog(env, 0);
        if (mainprogno < 0)
                return mainprogno;
+       insn_idx = 0;
        init_func_state(env, state->frame[0],
-                       BPF_MAIN_FUNC /* callsite */,
+                       insn_idx /* entry point */,
                        0 /* frameno */,
                        mainprogno /* subprogno */);
-       insn_idx = 0;
        for (;;) {
                struct bpf_insn_aux_data *aux = &env->insn_aux_data[insn_idx];
                struct bpf_func_state *frame = cur_frame(env);
@@ -4412,6 +4410,8 @@ static int do_check(struct bpf_verifier_env *env)
                        return -EFAULT;
                }
 
+               frame->insn_idx = insn_idx;
+
                insn = &insns[insn_idx];
                class = BPF_CLASS(insn->code);
 

Reply via email to