test_bpf: add tests checking that JIT/interpreter sets A and X to 0.
authorNicolas Schichan <nschichan@freebox.fr>
Tue, 4 Aug 2015 13:19:12 +0000 (15:19 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 7 Aug 2015 05:02:32 +0000 (22:02 -0700)
It is mandatory for the JIT or interpreter to reset the A and X
registers to 0 before running the filter. Check that it is the case on
various ALU and JMP instructions.

Signed-off-by: Nicolas Schichan <nschichan@freebox.fr>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
lib/test_bpf.c

index e6ef56df0dfea35a95f2d8bc8c6028b4bcd61a87..d1377390b3adda70bafe7464186e034d1fd7bd01 100644 (file)
@@ -4931,6 +4931,164 @@ static struct bpf_test tests[] = {
                },
                { {0x40, 0x88ee99ff } },
        },
+       /*
+        * verify that the interpreter or JIT correctly sets A and X
+        * to 0.
+        */
+       {
+               "ADD default X",
+               .u.insns = {
+                       /*
+                        * A = 0x42
+                        * A = A + X
+                        * ret A
+                        */
+                       BPF_STMT(BPF_LD | BPF_IMM, 0x42),
+                       BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x42 } },
+       },
+       {
+               "ADD default A",
+               .u.insns = {
+                       /*
+                        * A = A + 0x42
+                        * ret A
+                        */
+                       BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 0x42),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x42 } },
+       },
+       {
+               "SUB default X",
+               .u.insns = {
+                       /*
+                        * A = 0x66
+                        * A = A - X
+                        * ret A
+                        */
+                       BPF_STMT(BPF_LD | BPF_IMM, 0x66),
+                       BPF_STMT(BPF_ALU | BPF_SUB | BPF_X, 0),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x66 } },
+       },
+       {
+               "SUB default A",
+               .u.insns = {
+                       /*
+                        * A = A - -0x66
+                        * ret A
+                        */
+                       BPF_STMT(BPF_ALU | BPF_SUB | BPF_K, -0x66),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x66 } },
+       },
+       {
+               "MUL default X",
+               .u.insns = {
+                       /*
+                        * A = 0x42
+                        * A = A * X
+                        * ret A
+                        */
+                       BPF_STMT(BPF_LD | BPF_IMM, 0x42),
+                       BPF_STMT(BPF_ALU | BPF_MUL | BPF_X, 0),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x0 } },
+       },
+       {
+               "MUL default A",
+               .u.insns = {
+                       /*
+                        * A = A * 0x66
+                        * ret A
+                        */
+                       BPF_STMT(BPF_ALU | BPF_MUL | BPF_K, 0x66),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x0 } },
+       },
+       {
+               "DIV default X",
+               .u.insns = {
+                       /*
+                        * A = 0x42
+                        * A = A / X ; this halt the filter execution if X is 0
+                        * ret 0x42
+                        */
+                       BPF_STMT(BPF_LD | BPF_IMM, 0x42),
+                       BPF_STMT(BPF_ALU | BPF_DIV | BPF_X, 0),
+                       BPF_STMT(BPF_RET | BPF_K, 0x42),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x0 } },
+       },
+       {
+               "DIV default A",
+               .u.insns = {
+                       /*
+                        * A = A / 1
+                        * ret A
+                        */
+                       BPF_STMT(BPF_ALU | BPF_DIV | BPF_K, 0x1),
+                       BPF_STMT(BPF_RET | BPF_A, 0x0),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x0 } },
+       },
+       {
+               "JMP EQ default A",
+               .u.insns = {
+                       /*
+                        * cmp A, 0x0, 0, 1
+                        * ret 0x42
+                        * ret 0x66
+                        */
+                       BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0, 0, 1),
+                       BPF_STMT(BPF_RET | BPF_K, 0x42),
+                       BPF_STMT(BPF_RET | BPF_K, 0x66),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x42 } },
+       },
+       {
+               "JMP EQ default X",
+               .u.insns = {
+                       /*
+                        * A = 0x0
+                        * cmp A, X, 0, 1
+                        * ret 0x42
+                        * ret 0x66
+                        */
+                       BPF_STMT(BPF_LD | BPF_IMM, 0x0),
+                       BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0x0, 0, 1),
+                       BPF_STMT(BPF_RET | BPF_K, 0x42),
+                       BPF_STMT(BPF_RET | BPF_K, 0x66),
+               },
+               CLASSIC | FLAG_NO_DATA,
+               {},
+               { {0x1, 0x42 } },
+       },
 };
 
 static struct net_device dev;