Error messages for some bad programs have changed, partly because we now check for loops / out-of-bounds jumps before checking subprogs. Also added a test ("calls: interleaved functions") to ensure that subprogs are required to be contiguous. It wasn't entirely clear to me what "calls: wrong recursive calls" was meant to test for, since all of the JMP|CALL insns are unreachable. I've changed it so that they are now reachable, which causes static back-edges to be detected (since that, like insn reachability, is now tested before subprog boundaries are determined).
Signed-off-by: Edward Cree <ec...@solarflare.com> --- tools/testing/selftests/bpf/test_verifier.c | 51 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 3e7718b1a9ae..cc45a0b52439 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -646,7 +646,7 @@ static struct bpf_test tests[] = { .insns = { BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2), }, - .errstr = "not an exit", + .errstr = "jump out of range", .result = REJECT, }, { @@ -9442,13 +9442,13 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "last insn is not an exit or jmp", + .errstr = "insn 1 was in subprog 1, now 0", .result = REJECT, }, { "calls: wrong recursive calls", .insns = { - BPF_JMP_IMM(BPF_JA, 0, 0, 4), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), BPF_JMP_IMM(BPF_JA, 0, 0, 4), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -2), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -2), @@ -9457,7 +9457,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "jump out of range", + .errstr = "back-edge from insn", .result = REJECT, }, { @@ -9508,7 +9508,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "jump out of range", + .errstr = "insn 5 was in subprog 1, now 0", .result = REJECT, }, { @@ -9787,7 +9787,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_SCHED_CLS, - .errstr = "jump out of range from insn 1 to 4", + .errstr = "insn 5 was in subprog 1, now 0", .result = REJECT, }, { @@ -9803,13 +9803,12 @@ static struct bpf_test tests[] = { BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), BPF_EXIT_INSN(), - BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, - offsetof(struct __sk_buff, len)), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8), BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, -3), BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "jump out of range from insn 11 to 9", + .errstr = "insn 9 was in subprog 1, now 2", .result = REJECT, }, { @@ -9861,7 +9860,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "invalid destination", + .errstr = "jump out of range from insn 2 to -1", .result = REJECT, }, { @@ -9873,7 +9872,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "invalid destination", + .errstr = "jump out of range from insn 2 to -2147483646", .result = REJECT, }, { @@ -9886,7 +9885,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "jump out of range", + .errstr = "insn 1 was in subprog 0, now 1", .result = REJECT, }, { @@ -9899,7 +9898,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "jump out of range", + .errstr = "insn 4 was in subprog 1, now 0", .result = REJECT, }, { @@ -9913,7 +9912,7 @@ static struct bpf_test tests[] = { BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -2), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "not an exit", + .errstr = "jump out of range from insn 5 to 6", .result = REJECT, }, { @@ -9927,7 +9926,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "last insn", + .errstr = "insn_idx 5 is in subprog 1 but that starts at 4", .result = REJECT, }, { @@ -9942,7 +9941,7 @@ static struct bpf_test tests[] = { BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "last insn", + .errstr = "insn_idx 5 is in subprog 1 but that starts at 4", .result = REJECT, }, { @@ -9982,12 +9981,11 @@ static struct bpf_test tests[] = { BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), BPF_MOV64_REG(BPF_REG_0, BPF_REG_0), - BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, - offsetof(struct __sk_buff, len)), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8), BPF_EXIT_INSN(), }, .prog_type = BPF_PROG_TYPE_TRACEPOINT, - .errstr = "not an exit", + .errstr = "insn 10 was in subprog 2, now 1", .result = REJECT, }, { @@ -11423,6 +11421,21 @@ static struct bpf_test tests[] = { .errstr = "BPF_XADD stores into R2 packet", .prog_type = BPF_PROG_TYPE_XDP, }, + { + "calls: interleaved functions", + .insns = { + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 2), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), + BPF_EXIT_INSN(), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_TRACEPOINT, + .errstr = "subprog 0 is non-contiguous at 5", + .result = REJECT, + }, }; static int probe_filter_length(const struct bpf_insn *fp)