selftests: bpf: verifier: add tests for JSET interpretation
authorJakub Kicinski <jakub.kicinski@netronome.com>
Thu, 20 Dec 2018 06:13:05 +0000 (22:13 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 20 Dec 2018 16:28:28 +0000 (17:28 +0100)
Validate that the verifier reasons correctly about the bounds
and removes dead code based on results of JSET instruction.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
tools/testing/selftests/bpf/test_verifier.c

index 580fc9429147e10387fd7a4bcd833c3a15106f4a..b246931c46ef7a9a430bb0346b44d1e9fce7b41f 100644 (file)
@@ -14265,6 +14265,102 @@ static struct bpf_test tests[] = {
                .retval = 2,
                .data = { 1, 0, 0, 0, 0, 0, 0, 1, },
        },
+       {
+               "jset: known const compare",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .retval_unpriv = 1,
+               .result_unpriv = ACCEPT,
+               .retval = 1,
+               .result = ACCEPT,
+       },
+       {
+               "jset: known const compare bad",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .errstr_unpriv = "!read_ok",
+               .result_unpriv = REJECT,
+               .errstr = "!read_ok",
+               .result = REJECT,
+       },
+       {
+               "jset: unknown const compare taken",
+               .insns = {
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_prandom_u32),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
+                       BPF_JMP_IMM(BPF_JA, 0, 0, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .errstr_unpriv = "!read_ok",
+               .result_unpriv = REJECT,
+               .errstr = "!read_ok",
+               .result = REJECT,
+       },
+       {
+               "jset: unknown const compare not taken",
+               .insns = {
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_prandom_u32),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .errstr_unpriv = "!read_ok",
+               .result_unpriv = REJECT,
+               .errstr = "!read_ok",
+               .result = REJECT,
+       },
+       {
+               "jset: half-known const compare",
+               .insns = {
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_prandom_u32),
+                       BPF_ALU64_IMM(BPF_OR, BPF_REG_0, 2),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 3, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .result_unpriv = ACCEPT,
+               .result = ACCEPT,
+       },
+       {
+               "jset: range",
+               .insns = {
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_prandom_u32),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xff),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0xf0, 3),
+                       BPF_JMP_IMM(BPF_JLT, BPF_REG_1, 0x10, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_EXIT_INSN(),
+                       BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0x10, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0x10, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .result_unpriv = ACCEPT,
+               .result = ACCEPT,
+       },
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)