bpf: fix max call depth check
authorAlexei Starovoitov <ast@kernel.org>
Mon, 25 Dec 2017 21:15:42 +0000 (13:15 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 27 Dec 2017 17:36:23 +0000 (18:36 +0100)
fix off by one error in max call depth check
and add a test

Fixes: f4d7e40a5b71 ("bpf: introduce function calls (verification)")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
kernel/bpf/verifier.c
tools/testing/selftests/bpf/test_verifier.c

index 738e919efdf03782dcd99ef2679dcb6af9768ef2..52ad60b3b8becc8d1f2785d9a37616130086f744 100644 (file)
@@ -2126,9 +2126,9 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
        struct bpf_func_state *caller, *callee;
        int i, subprog, target_insn;
 
-       if (state->curframe >= MAX_CALL_FRAMES) {
+       if (state->curframe + 1 >= MAX_CALL_FRAMES) {
                verbose(env, "the call stack of %d frames is too deep\n",
-                       state->curframe);
+                       state->curframe + 2);
                return -E2BIG;
        }
 
index b5a7a6c530dc821a7b07f5e2c6cf897f3954fdfe..5d0a574ce2700fc2a99919e5db497787701de1d6 100644 (file)
@@ -8884,6 +8884,41 @@ static struct bpf_test tests[] = {
                .result = REJECT,
                .errstr = "combined stack",
        },
+       {
+               "calls: stack depth check using three frames. test5",
+               .insns = {
+                       /* main */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call A */
+                       BPF_EXIT_INSN(),
+                       /* A */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call B */
+                       BPF_EXIT_INSN(),
+                       /* B */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call C */
+                       BPF_EXIT_INSN(),
+                       /* C */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call D */
+                       BPF_EXIT_INSN(),
+                       /* D */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call E */
+                       BPF_EXIT_INSN(),
+                       /* E */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call F */
+                       BPF_EXIT_INSN(),
+                       /* F */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call G */
+                       BPF_EXIT_INSN(),
+                       /* G */
+                       BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 1), /* call H */
+                       BPF_EXIT_INSN(),
+                       /* H */
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_XDP,
+               .errstr = "call stack",
+               .result = REJECT,
+       },
        {
                "calls: spill into caller stack frame",
                .insns = {