bpf: add various test cases for alu op on mixed dst register types
authorDaniel Borkmann <daniel@iogearbox.net>
Sat, 5 Jan 2019 23:54:38 +0000 (00:54 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 6 Jan 2019 05:32:38 +0000 (21:32 -0800)
Add couple of test_verifier tests to check sanitation of alu op insn
with pointer and scalar type coming from different paths. This also
includes BPF insns of the test reproducer provided by Jann Horn.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/test_verifier.c

index 10d44446e8013a19d8c01e5e15a94a919bae94cb..2fd90d4568926d13542783c870507d43a6d6bb64 100644 (file)
@@ -6933,6 +6933,126 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .retval = 1,
        },
+       {
+               "map access: mixing value pointer and scalar, 1",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different pointers or scalars",
+               .retval = 0,
+       },
+       {
+               "map access: mixing value pointer and scalar, 2",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different maps or paths",
+               .retval = 0,
+       },
+       {
+               "sanitation: alu with different scalars",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       BPF_MOV64_IMM(BPF_REG_2, 42),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100001),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .retval = 0x100000,
+       },
        {
                "map access: value_ptr += known scalar, upper oob arith, test 1",
                .insns = {