bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
/*
|
|
|
|
* Testsuite for eBPF verifier
|
|
|
|
*
|
|
|
|
* Copyright (c) 2014 PLUMgrid, http://plumgrid.com
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
|
|
* License as published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <linux/bpf.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <linux/unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <linux/filter.h>
|
2015-03-14 01:57:43 +07:00
|
|
|
#include <stddef.h>
|
2015-10-08 12:23:23 +07:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <sys/resource.h>
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
#include "libbpf.h"
|
|
|
|
|
|
|
|
#define MAX_INSNS 512
|
|
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
|
|
|
|
2015-10-08 12:23:23 +07:00
|
|
|
#define MAX_FIXUPS 8
|
|
|
|
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
struct bpf_test {
|
|
|
|
const char *descr;
|
|
|
|
struct bpf_insn insns[MAX_INSNS];
|
2015-10-08 12:23:23 +07:00
|
|
|
int fixup[MAX_FIXUPS];
|
|
|
|
int prog_array_fixup[MAX_FIXUPS];
|
2016-09-28 21:54:32 +07:00
|
|
|
int test_val_map_fixup[MAX_FIXUPS];
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
const char *errstr;
|
2015-10-08 12:23:23 +07:00
|
|
|
const char *errstr_unpriv;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
enum {
|
2015-10-08 12:23:23 +07:00
|
|
|
UNDEF,
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
ACCEPT,
|
|
|
|
REJECT
|
2015-10-08 12:23:23 +07:00
|
|
|
} result, result_unpriv;
|
2015-06-05 00:11:54 +07:00
|
|
|
enum bpf_prog_type prog_type;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
};
|
|
|
|
|
2016-09-28 21:54:32 +07:00
|
|
|
/* Note we want this to be 64 bit aligned so that the end of our array is
|
|
|
|
* actually the end of the structure.
|
|
|
|
*/
|
|
|
|
#define MAX_ENTRIES 11
|
|
|
|
struct test_val {
|
|
|
|
unsigned index;
|
|
|
|
int foo[MAX_ENTRIES];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct other_val {
|
|
|
|
unsigned int action[32];
|
|
|
|
};
|
|
|
|
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
static struct bpf_test tests[] = {
|
|
|
|
{
|
|
|
|
"add+sub+mul",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 1),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 3),
|
|
|
|
BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1),
|
|
|
|
BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unreachable",
|
|
|
|
.insns = {
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "unreachable",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unreachable2",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "unreachable",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"out of range jump",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "jump out of range",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"out of range jump2",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, -2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "jump out of range",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"test1 ld_imm64",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 1),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 1),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid BPF_LD_IMM insn",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"test2 ld_imm64",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 1),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid BPF_LD_IMM insn",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"test3 ld_imm64",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
|
|
|
|
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 0),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 1),
|
|
|
|
BPF_LD_IMM64(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_ld_imm64 insn",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"test4 ld_imm64",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_ld_imm64 insn",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"test5 ld_imm64",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_ld_imm64 insn",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"no bpf_exit",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2),
|
|
|
|
},
|
|
|
|
.errstr = "jump out of range",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"loop (back-edge)",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "back-edge",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"loop2 (back-edge)",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, -4),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "back-edge",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"conditional loop",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "back-edge",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"read uninitialized register",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R2 !read_ok",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"read invalid register",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R15 is invalid",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"program doesn't init R0 before exit",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R0 !read_ok",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
2014-10-21 04:54:57 +07:00
|
|
|
{
|
|
|
|
"program doesn't init R0 before exit in all branches",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R0 !read_ok",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2014-10-21 04:54:57 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
{
|
|
|
|
"stack out of bounds",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid stack",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid call insn1",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "BPF_CALL uses reserved",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid call insn2",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "BPF_CALL uses reserved",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid function call",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid func 1234567",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"uninitialized stack1",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
2014-11-14 08:36:50 +07:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {2},
|
|
|
|
.errstr = "invalid indirect read from stack",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"uninitialized stack2",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid read from stack",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
2016-09-20 05:26:14 +07:00
|
|
|
{
|
|
|
|
"invalid argument register",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R1 !read_ok",
|
|
|
|
.result = REJECT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"non-invalid argument register",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_1),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_cgroup_classid),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
{
|
|
|
|
"check valid spill/fill",
|
|
|
|
.insns = {
|
|
|
|
/* spill R1(ctx) into stack */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
|
|
|
|
/* fill it back into R2 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
|
|
|
|
|
|
|
|
/* should be able to access R0 = *(R2 + 8) */
|
2015-03-01 18:31:41 +07:00
|
|
|
/* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
.result = ACCEPT,
|
2015-10-08 12:23:23 +07:00
|
|
|
.result_unpriv = REJECT,
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
},
|
bpf, samples: add test cases for raw stack
This adds test cases mostly around ARG_PTR_TO_RAW_STACK to check the
verifier behaviour.
[...]
#84 raw_stack: no skb_load_bytes OK
#85 raw_stack: skb_load_bytes, no init OK
#86 raw_stack: skb_load_bytes, init OK
#87 raw_stack: skb_load_bytes, spilled regs around bounds OK
#88 raw_stack: skb_load_bytes, spilled regs corruption OK
#89 raw_stack: skb_load_bytes, spilled regs corruption 2 OK
#90 raw_stack: skb_load_bytes, spilled regs + data OK
#91 raw_stack: skb_load_bytes, invalid access 1 OK
#92 raw_stack: skb_load_bytes, invalid access 2 OK
#93 raw_stack: skb_load_bytes, invalid access 3 OK
#94 raw_stack: skb_load_bytes, invalid access 4 OK
#95 raw_stack: skb_load_bytes, invalid access 5 OK
#96 raw_stack: skb_load_bytes, invalid access 6 OK
#97 raw_stack: skb_load_bytes, large access OK
Summary: 98 PASSED, 0 FAILED
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-13 05:10:54 +07:00
|
|
|
{
|
|
|
|
"check valid spill/fill, skb mark",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_1),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -8),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = ACCEPT,
|
|
|
|
},
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
{
|
|
|
|
"check corrupted spill/fill",
|
|
|
|
.insns = {
|
|
|
|
/* spill R1(ctx) into stack */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
|
|
|
|
/* mess up with R1 pointer on stack */
|
|
|
|
BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23),
|
|
|
|
|
|
|
|
/* fill back into R0 should fail */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
|
|
|
|
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "attempt to corrupt spilled",
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
.errstr = "corrupted spill",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid src register in STX",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R15 is invalid",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid dst register in STX",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R14 is invalid",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid dst register in ST",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_B, 14, -1, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R14 is invalid",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid src register in LDX",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R12 is invalid",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid dst register in LDX",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "R11 is invalid",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"junk insn",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(0, 0, 0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid BPF_LD_IMM",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"junk insn2",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(1, 0, 0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "BPF_LDX uses reserved fields",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"junk insn3",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(-1, 0, 0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid BPF_ALU opcode f0",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"junk insn4",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(-1, -1, -1, -1, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid BPF_ALU opcode f0",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"junk insn5",
|
|
|
|
.insns = {
|
|
|
|
BPF_RAW_INSN(0x7f, -1, -1, -1, -1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "BPF_ALU uses reserved fields",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"misaligned read from stack",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "misaligned access",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map_fd for function call",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
2014-11-14 08:36:50 +07:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "fd 0 is not pointing to valid bpf_map",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"don't check return value before access",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
2014-11-14 08:36:50 +07:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {3},
|
|
|
|
.errstr = "R0 invalid mem access 'map_value_or_null'",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"access memory with incorrect alignment",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
2014-11-14 08:36:50 +07:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {3},
|
|
|
|
.errstr = "misaligned access",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sometimes access memory with incorrect alignment",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
2014-11-14 08:36:50 +07:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {3},
|
|
|
|
.errstr = "R0 invalid mem access",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
2014-09-30 08:50:02 +07:00
|
|
|
{
|
|
|
|
"jump test 1",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 08:50:02 +07:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"jump test 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 14),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 11),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 8),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 5),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 08:50:02 +07:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"jump test 3",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 19),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 15),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 11),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 7),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
2014-11-14 08:36:50 +07:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
|
2014-09-30 08:50:02 +07:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {24},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 08:50:02 +07:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"jump test 4",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 08:50:02 +07:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
2014-10-29 05:11:42 +07:00
|
|
|
{
|
|
|
|
"jump test 5",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 2),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-10-29 05:11:42 +07:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
2015-03-14 01:57:43 +07:00
|
|
|
{
|
|
|
|
"access skb fields ok",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, len)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, pkt_type)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, queue_mapping)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
|
2015-03-17 08:06:02 +07:00
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, protocol)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, vlan_present)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, vlan_tci)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
|
2015-03-14 01:57:43 +07:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"access skb fields bad1",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -4),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"access skb fields bad2",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 9),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, pkt_type)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {4},
|
|
|
|
.errstr = "different pointers",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2015-03-14 01:57:43 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"access skb fields bad3",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, pkt_type)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, -12),
|
|
|
|
},
|
|
|
|
.fixup = {6},
|
|
|
|
.errstr = "different pointers",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2015-03-14 01:57:43 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
2015-04-16 06:19:33 +07:00
|
|
|
{
|
|
|
|
"access skb fields bad4",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 3),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, len)),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
|
|
|
BPF_JMP_IMM(BPF_JA, 0, 0, -13),
|
|
|
|
},
|
|
|
|
.fixup = {7},
|
|
|
|
.errstr = "different pointers",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2015-04-16 06:19:33 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
2015-06-05 00:11:54 +07:00
|
|
|
{
|
|
|
|
"check skb->mark is not writeable by sockets",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
2015-06-05 00:11:54 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"check skb->tc_index is not writeable by sockets",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, tc_index)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
2015-06-05 00:11:54 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"check non-u32 access to cb",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, cb[0])),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
2015-06-05 00:11:54 +07:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"check out of range skb->cb access",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
2015-10-08 12:23:23 +07:00
|
|
|
offsetof(struct __sk_buff, cb[0]) + 256),
|
2015-06-05 00:11:54 +07:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access",
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "",
|
2015-06-05 00:11:54 +07:00
|
|
|
.result = REJECT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_ACT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"write skb fields from socket prog",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, cb[4])),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, tc_index)),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, cb[0])),
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, cb[2])),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
2015-06-05 00:11:54 +07:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"write skb fields from tc_cls_act prog",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, cb[0])),
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, tc_index)),
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, tc_index)),
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, cb[3])),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
.errstr_unpriv = "",
|
|
|
|
.result_unpriv = REJECT,
|
2015-06-05 00:11:54 +07:00
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2015-07-24 04:24:40 +07:00
|
|
|
{
|
|
|
|
"PTR_TO_STACK store/load",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"PTR_TO_STACK store/load - bad alignment on off",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "misaligned access off -6 size 8",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"PTR_TO_STACK store/load - bad alignment on reg",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "misaligned access off -2 size 8",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"PTR_TO_STACK store/load - out of bounds low",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -80000),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack off=-79992 size=8",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"PTR_TO_STACK store/load - out of bounds high",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack off=0 size=8",
|
|
|
|
},
|
2015-10-08 12:23:23 +07:00
|
|
|
{
|
|
|
|
"unpriv: return pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: add const to pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R1 pointer arithmetic",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: add pointer to pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R1 pointer arithmetic",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: neg pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_ALU64_IMM(BPF_NEG, BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R1 pointer arithmetic",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: cmp pointer with const",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: cmp pointer with pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R10 pointer comparison",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: check that printk is disallowed",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "unknown func 6",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: pass pointer to helper function",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {3},
|
|
|
|
.errstr_unpriv = "R4 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: indirectly pass pointer on stack to helper function",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {3},
|
|
|
|
.errstr = "invalid indirect read from stack off -8+0 size 8",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: mangle pointer on stack 1",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
|
|
|
|
BPF_ST_MEM(BPF_W, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "attempt to corrupt spilled",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: mangle pointer on stack 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
|
|
|
|
BPF_ST_MEM(BPF_B, BPF_REG_10, -1, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "attempt to corrupt spilled",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: read pointer from stack in small chunks",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid size",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: write pointer into ctx",
|
|
|
|
.insns = {
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr = "invalid bpf_context access",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: write pointer into map elem value",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {3},
|
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: partial copy of pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV32_REG(BPF_REG_1, BPF_REG_10),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "R10 partial copy",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: pass pointer to tail_call",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_1),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.prog_array_fixup = {1},
|
|
|
|
.errstr_unpriv = "R3 leaks addr into helper",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: cmp map pointer with zero",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 0),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {1},
|
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: write into frame pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_10, BPF_REG_1),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "frame pointer is read only",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: cmp of frame pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_10, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "R10 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: cmp of stack pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "R2 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"unpriv: obfuscate stack pointer",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr_unpriv = "R2 pointer arithmetic",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
bpf, samples: add test cases for raw stack
This adds test cases mostly around ARG_PTR_TO_RAW_STACK to check the
verifier behaviour.
[...]
#84 raw_stack: no skb_load_bytes OK
#85 raw_stack: skb_load_bytes, no init OK
#86 raw_stack: skb_load_bytes, init OK
#87 raw_stack: skb_load_bytes, spilled regs around bounds OK
#88 raw_stack: skb_load_bytes, spilled regs corruption OK
#89 raw_stack: skb_load_bytes, spilled regs corruption 2 OK
#90 raw_stack: skb_load_bytes, spilled regs + data OK
#91 raw_stack: skb_load_bytes, invalid access 1 OK
#92 raw_stack: skb_load_bytes, invalid access 2 OK
#93 raw_stack: skb_load_bytes, invalid access 3 OK
#94 raw_stack: skb_load_bytes, invalid access 4 OK
#95 raw_stack: skb_load_bytes, invalid access 5 OK
#96 raw_stack: skb_load_bytes, invalid access 6 OK
#97 raw_stack: skb_load_bytes, large access OK
Summary: 98 PASSED, 0 FAILED
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-13 05:10:54 +07:00
|
|
|
{
|
|
|
|
"raw_stack: no skb_load_bytes",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
/* Call to skb_load_bytes() omitted. */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid read from stack off -8+0 size 8",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2016-09-20 05:26:14 +07:00
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, negative len",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, -8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, negative len 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, ~0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, zero len",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
bpf, samples: add test cases for raw stack
This adds test cases mostly around ARG_PTR_TO_RAW_STACK to check the
verifier behaviour.
[...]
#84 raw_stack: no skb_load_bytes OK
#85 raw_stack: skb_load_bytes, no init OK
#86 raw_stack: skb_load_bytes, init OK
#87 raw_stack: skb_load_bytes, spilled regs around bounds OK
#88 raw_stack: skb_load_bytes, spilled regs corruption OK
#89 raw_stack: skb_load_bytes, spilled regs corruption 2 OK
#90 raw_stack: skb_load_bytes, spilled regs + data OK
#91 raw_stack: skb_load_bytes, invalid access 1 OK
#92 raw_stack: skb_load_bytes, invalid access 2 OK
#93 raw_stack: skb_load_bytes, invalid access 3 OK
#94 raw_stack: skb_load_bytes, invalid access 4 OK
#95 raw_stack: skb_load_bytes, invalid access 5 OK
#96 raw_stack: skb_load_bytes, invalid access 6 OK
#97 raw_stack: skb_load_bytes, large access OK
Summary: 98 PASSED, 0 FAILED
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-13 05:10:54 +07:00
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, no init",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, init",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_6, 0, 0xcafe),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, spilled regs around bounds",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
|
|
|
|
offsetof(struct __sk_buff, priority)),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, spilled regs corruption",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), /* fill ctx into R0 */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "R0 invalid mem access 'inv'",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, spilled regs corruption 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill ctx into R3 */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
|
|
|
|
offsetof(struct __sk_buff, priority)),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_3,
|
|
|
|
offsetof(struct __sk_buff, pkt_type)),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "R3 invalid mem access 'inv'",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, spilled regs + data",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -16),
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, -8), /* spill ctx from R1 */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), /* spill ctx from R1 */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8), /* spill ctx from R1 */
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, -8), /* fill ctx into R0 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 8), /* fill ctx into R2 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6, 0), /* fill data into R3 */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0,
|
|
|
|
offsetof(struct __sk_buff, mark)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_2,
|
|
|
|
offsetof(struct __sk_buff, priority)),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, invalid access 1",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -513),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3 off=-513 access_size=8",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, invalid access 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 8),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3 off=-1 access_size=8",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, invalid access 3",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0xffffffff),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0xffffffff),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3 off=-1 access_size=-1",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, invalid access 4",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3 off=-1 access_size=2147483647",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, invalid access 5",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0x7fffffff),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3 off=-512 access_size=2147483647",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, invalid access 6",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid stack type R3 off=-512 access_size=0",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"raw_stack: skb_load_bytes, large access",
|
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -512),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 512),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2016-05-06 09:49:15 +07:00
|
|
|
{
|
2016-08-12 08:17:17 +07:00
|
|
|
"direct packet access: test1",
|
2016-05-06 09:49:15 +07:00
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
2016-08-12 08:17:17 +07:00
|
|
|
"direct packet access: test2",
|
2016-05-06 09:49:15 +07:00
|
|
|
.insns = {
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_5, BPF_REG_3),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_4, 15),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_3, 7),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_3, 12),
|
|
|
|
BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 14),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
|
|
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 48),
|
|
|
|
BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 48),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_3),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 1),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_3, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
2016-08-12 08:17:17 +07:00
|
|
|
"direct packet access: test3",
|
2016-05-06 09:49:15 +07:00
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access off=76",
|
|
|
|
.result = REJECT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
|
|
|
|
},
|
|
|
|
{
|
2016-09-20 05:26:14 +07:00
|
|
|
"direct packet access: test4 (write)",
|
2016-05-06 09:49:15 +07:00
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
|
|
|
|
BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2016-09-20 05:26:14 +07:00
|
|
|
.result = ACCEPT,
|
2016-05-06 09:49:15 +07:00
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
bpf: fix range propagation on direct packet access
LLVM can generate code that tests for direct packet access via
skb->data/data_end in a way that currently gets rejected by the
verifier, example:
[...]
7: (61) r3 = *(u32 *)(r6 +80)
8: (61) r9 = *(u32 *)(r6 +76)
9: (bf) r2 = r9
10: (07) r2 += 54
11: (3d) if r3 >= r2 goto pc+12
R1=inv R2=pkt(id=0,off=54,r=0) R3=pkt_end R4=inv R6=ctx
R9=pkt(id=0,off=0,r=0) R10=fp
12: (18) r4 = 0xffffff7a
14: (05) goto pc+430
[...]
from 11 to 24: R1=inv R2=pkt(id=0,off=54,r=0) R3=pkt_end R4=inv
R6=ctx R9=pkt(id=0,off=0,r=0) R10=fp
24: (7b) *(u64 *)(r10 -40) = r1
25: (b7) r1 = 0
26: (63) *(u32 *)(r6 +56) = r1
27: (b7) r2 = 40
28: (71) r8 = *(u8 *)(r9 +20)
invalid access to packet, off=20 size=1, R9(id=0,off=0,r=0)
The reason why this gets rejected despite a proper test is that we
currently call find_good_pkt_pointers() only in case where we detect
tests like rX > pkt_end, where rX is of type pkt(id=Y,off=Z,r=0) and
derived, for example, from a register of type pkt(id=Y,off=0,r=0)
pointing to skb->data. find_good_pkt_pointers() then fills the range
in the current branch to pkt(id=Y,off=0,r=Z) on success.
For above case, we need to extend that to recognize pkt_end >= rX
pattern and mark the other branch that is taken on success with the
appropriate pkt(id=Y,off=0,r=Z) type via find_good_pkt_pointers().
Since eBPF operates on BPF_JGT (>) and BPF_JGE (>=), these are the
only two practical options to test for from what LLVM could have
generated, since there's no such thing as BPF_JLT (<) or BPF_JLE (<=)
that we would need to take into account as well.
After the fix:
[...]
7: (61) r3 = *(u32 *)(r6 +80)
8: (61) r9 = *(u32 *)(r6 +76)
9: (bf) r2 = r9
10: (07) r2 += 54
11: (3d) if r3 >= r2 goto pc+12
R1=inv R2=pkt(id=0,off=54,r=0) R3=pkt_end R4=inv R6=ctx
R9=pkt(id=0,off=0,r=0) R10=fp
12: (18) r4 = 0xffffff7a
14: (05) goto pc+430
[...]
from 11 to 24: R1=inv R2=pkt(id=0,off=54,r=54) R3=pkt_end R4=inv
R6=ctx R9=pkt(id=0,off=0,r=54) R10=fp
24: (7b) *(u64 *)(r10 -40) = r1
25: (b7) r1 = 0
26: (63) *(u32 *)(r6 +56) = r1
27: (b7) r2 = 40
28: (71) r8 = *(u8 *)(r9 +20)
29: (bf) r1 = r8
30: (25) if r8 > 0x3c goto pc+47
R1=inv56 R2=imm40 R3=pkt_end R4=inv R6=ctx R8=inv56
R9=pkt(id=0,off=0,r=54) R10=fp
31: (b7) r1 = 1
[...]
Verifier test cases are also added in this work, one that demonstrates
the mentioned example here and one that tries a bad packet access for
the current/fall-through branch (the one with types pkt(id=X,off=Y,r=0),
pkt(id=X,off=0,r=0)), then a case with good and bad accesses, and two
with both test variants (>, >=).
Fixes: 969bf05eb3ce ("bpf: direct packet access")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-08 06:03:42 +07:00
|
|
|
{
|
|
|
|
"direct packet access: test5 (pkt_end >= reg, good access)",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"direct packet access: test6 (pkt_end >= reg, bad access)",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 3),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.result = REJECT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"direct packet access: test7 (pkt_end >= reg, both accesses)",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 3),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.result = REJECT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"direct packet access: test8 (double test, variant 1)",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 4),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"direct packet access: test9 (double test, variant 2)",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2016-09-20 05:26:14 +07:00
|
|
|
{
|
|
|
|
"direct packet access: test10 (write invalid)",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_STX_MEM(BPF_B, BPF_REG_2, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.result = REJECT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2016-08-12 08:17:17 +07:00
|
|
|
{
|
|
|
|
"helper access to packet: test1, valid packet_ptr range",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 5),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {5},
|
|
|
|
.result_unpriv = ACCEPT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test2, unchecked packet_ptr",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data)),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {1},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test3, variable add",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 10),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_5, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_5),
|
|
|
|
BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 4),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_4),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {11},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test4, packet_ptr with bad range",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {7},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test5, packet_ptr with too short range",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct xdp_md, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 3),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {6},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
|
|
},
|
2016-09-20 05:26:14 +07:00
|
|
|
{
|
|
|
|
"helper access to packet: test6, cls valid packet_ptr range",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 5),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {5},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test7, cls unchecked packet_ptr",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {1},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test8, cls variable add",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 10),
|
|
|
|
BPF_LDX_MEM(BPF_B, BPF_REG_5, BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_5),
|
|
|
|
BPF_MOV64_REG(BPF_REG_5, BPF_REG_4),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_5, BPF_REG_3, 4),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_4),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {11},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test9, cls packet_ptr with bad range",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {7},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test10, cls packet_ptr with too short range",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_4, BPF_REG_3, 3),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {6},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test11, cls unsuitable helper 1",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_7, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 42),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_store_bytes),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "helper access to the packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test12, cls unsuitable helper 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 8),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_6, BPF_REG_7, 3),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 4),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "helper access to the packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test13, cls helper ok",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test14, cls helper fail sub",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "type=inv expected=fp",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test15, cls helper fail range 1",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 8),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test16, cls helper fail range 2",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, -9),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test17, cls helper fail range 3",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, ~0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test18, cls helper fail range zero",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test19, pkt end as input",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "R1 type=pkt_end expected=fp",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"helper access to packet: test20, wrong reg",
|
|
|
|
.insns = {
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data)),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
|
|
|
|
offsetof(struct __sk_buff, data_end)),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
|
|
|
|
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_7, 6),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_2, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_3, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_4, 0),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_5, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_csum_diff),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid access to packet",
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2016-09-28 21:54:32 +07:00
|
|
|
{
|
|
|
|
"valid map access into an array with a constant",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid map access into an array with a register",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 4),
|
|
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid map access into an array with a variable",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JGE, BPF_REG_1, MAX_ENTRIES, 3),
|
|
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"valid map access into an array with a signed variable",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
|
|
|
|
BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 0xffffffff, 1),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 0),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
|
|
|
|
BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 0),
|
|
|
|
BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr_unpriv = "R0 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map access into an array with a constant",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, (MAX_ENTRIES + 1) << 2,
|
|
|
|
offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr = "invalid access to map value, value_size=48 off=48 size=8",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map access into an array with a register",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, MAX_ENTRIES + 1),
|
|
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr = "R0 min value is outside of the array range",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map access into an array with a variable",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map access into an array with no floor check",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES),
|
|
|
|
BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 0),
|
|
|
|
BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map access into an array with a invalid max check",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES + 1),
|
|
|
|
BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 1),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 0),
|
|
|
|
BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3},
|
|
|
|
.errstr = "invalid access to map value, value_size=48 off=44 size=8",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"invalid map access into an array with a invalid max check",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
|
|
|
|
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
|
|
|
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
|
|
|
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
|
|
|
|
BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_8),
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, offsetof(struct test_val, foo)),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.test_val_map_fixup = {3, 11},
|
|
|
|
.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
|
|
|
|
.result = REJECT,
|
|
|
|
},
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
static int probe_filter_length(struct bpf_insn *fp)
|
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
for (len = MAX_INSNS - 1; len > 0; --len)
|
|
|
|
if (fp[len].code != 0 || fp[len].imm != 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
return len + 1;
|
|
|
|
}
|
|
|
|
|
2016-09-28 21:54:32 +07:00
|
|
|
static int create_map(size_t val_size, int num)
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
{
|
|
|
|
int map_fd;
|
|
|
|
|
2015-10-08 12:23:23 +07:00
|
|
|
map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
|
2016-09-28 21:54:32 +07:00
|
|
|
sizeof(long long), val_size, num, 0);
|
2015-10-08 12:23:23 +07:00
|
|
|
if (map_fd < 0)
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
printf("failed to create map '%s'\n", strerror(errno));
|
2015-10-08 12:23:23 +07:00
|
|
|
|
|
|
|
return map_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int create_prog_array(void)
|
|
|
|
{
|
|
|
|
int map_fd;
|
|
|
|
|
|
|
|
map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY,
|
2016-03-08 12:57:20 +07:00
|
|
|
sizeof(int), sizeof(int), 4, 0);
|
2015-10-08 12:23:23 +07:00
|
|
|
if (map_fd < 0)
|
|
|
|
printf("failed to create prog_array '%s'\n", strerror(errno));
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
|
|
|
|
return map_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int test(void)
|
|
|
|
{
|
2014-10-29 05:11:42 +07:00
|
|
|
int prog_fd, i, pass_cnt = 0, err_cnt = 0;
|
2015-10-08 12:23:23 +07:00
|
|
|
bool unpriv = geteuid() != 0;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
|
|
|
struct bpf_insn *prog = tests[i].insns;
|
2015-06-05 00:11:54 +07:00
|
|
|
int prog_type = tests[i].prog_type;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
int prog_len = probe_filter_length(prog);
|
|
|
|
int *fixup = tests[i].fixup;
|
2015-10-08 12:23:23 +07:00
|
|
|
int *prog_array_fixup = tests[i].prog_array_fixup;
|
2016-09-28 21:54:32 +07:00
|
|
|
int *test_val_map_fixup = tests[i].test_val_map_fixup;
|
2015-10-08 12:23:23 +07:00
|
|
|
int expected_result;
|
|
|
|
const char *expected_errstr;
|
2016-09-28 21:54:32 +07:00
|
|
|
int map_fd = -1, prog_array_fd = -1, test_val_map_fd = -1;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
|
|
|
|
if (*fixup) {
|
2016-09-28 21:54:32 +07:00
|
|
|
map_fd = create_map(sizeof(long long), 1024);
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
|
|
|
|
do {
|
|
|
|
prog[*fixup].imm = map_fd;
|
|
|
|
fixup++;
|
|
|
|
} while (*fixup);
|
|
|
|
}
|
2015-10-08 12:23:23 +07:00
|
|
|
if (*prog_array_fixup) {
|
|
|
|
prog_array_fd = create_prog_array();
|
|
|
|
|
|
|
|
do {
|
|
|
|
prog[*prog_array_fixup].imm = prog_array_fd;
|
|
|
|
prog_array_fixup++;
|
|
|
|
} while (*prog_array_fixup);
|
|
|
|
}
|
2016-09-28 21:54:32 +07:00
|
|
|
if (*test_val_map_fixup) {
|
|
|
|
/* Unprivileged can't create a hash map.*/
|
|
|
|
if (unpriv)
|
|
|
|
continue;
|
|
|
|
test_val_map_fd = create_map(sizeof(struct test_val),
|
|
|
|
256);
|
|
|
|
do {
|
|
|
|
prog[*test_val_map_fixup].imm = test_val_map_fd;
|
|
|
|
test_val_map_fixup++;
|
|
|
|
} while (*test_val_map_fixup);
|
|
|
|
}
|
|
|
|
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
printf("#%d %s ", i, tests[i].descr);
|
|
|
|
|
2015-06-05 00:11:54 +07:00
|
|
|
prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
|
|
|
|
prog, prog_len * sizeof(struct bpf_insn),
|
2015-03-26 02:49:23 +07:00
|
|
|
"GPL", 0);
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
|
2015-10-08 12:23:23 +07:00
|
|
|
if (unpriv && tests[i].result_unpriv != UNDEF)
|
|
|
|
expected_result = tests[i].result_unpriv;
|
|
|
|
else
|
|
|
|
expected_result = tests[i].result;
|
|
|
|
|
|
|
|
if (unpriv && tests[i].errstr_unpriv)
|
|
|
|
expected_errstr = tests[i].errstr_unpriv;
|
|
|
|
else
|
|
|
|
expected_errstr = tests[i].errstr;
|
|
|
|
|
|
|
|
if (expected_result == ACCEPT) {
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
if (prog_fd < 0) {
|
|
|
|
printf("FAIL\nfailed to load prog '%s'\n",
|
|
|
|
strerror(errno));
|
|
|
|
printf("%s", bpf_log_buf);
|
2014-10-29 05:11:42 +07:00
|
|
|
err_cnt++;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (prog_fd >= 0) {
|
|
|
|
printf("FAIL\nunexpected success to load\n");
|
|
|
|
printf("%s", bpf_log_buf);
|
2014-10-29 05:11:42 +07:00
|
|
|
err_cnt++;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
goto fail;
|
|
|
|
}
|
2015-10-08 12:23:23 +07:00
|
|
|
if (strstr(bpf_log_buf, expected_errstr) == 0) {
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
printf("FAIL\nunexpected error message: %s",
|
|
|
|
bpf_log_buf);
|
2014-10-29 05:11:42 +07:00
|
|
|
err_cnt++;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-29 05:11:42 +07:00
|
|
|
pass_cnt++;
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
printf("OK\n");
|
|
|
|
fail:
|
|
|
|
if (map_fd >= 0)
|
|
|
|
close(map_fd);
|
2015-10-08 12:23:23 +07:00
|
|
|
if (prog_array_fd >= 0)
|
|
|
|
close(prog_array_fd);
|
2016-09-28 21:54:32 +07:00
|
|
|
if (test_val_map_fd >= 0)
|
|
|
|
close(test_val_map_fd);
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
close(prog_fd);
|
|
|
|
|
|
|
|
}
|
2014-10-29 05:11:42 +07:00
|
|
|
printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt);
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
2015-10-08 12:23:23 +07:00
|
|
|
struct rlimit r = {1 << 20, 1 << 20};
|
|
|
|
|
|
|
|
setrlimit(RLIMIT_MEMLOCK, &r);
|
bpf: mini eBPF library, test stubs and verifier testsuite
1.
the library includes a trivial set of BPF syscall wrappers:
int bpf_create_map(int key_size, int value_size, int max_entries);
int bpf_update_elem(int fd, void *key, void *value);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_get_next_key(int fd, void *key, void *next_key);
int bpf_prog_load(enum bpf_prog_type prog_type,
const struct sock_filter_int *insns, int insn_len,
const char *license);
bpf_prog_load() stores verifier log into global bpf_log_buf[] array
and BPF_*() macros to build instructions
2.
test stubs configure eBPF infra with 'unspec' map and program types.
These are fake types used by user space testsuite only.
3.
verifier tests valid and invalid programs and expects predefined
error log messages from kernel.
40 tests so far.
$ sudo ./test_verifier
#0 add+sub+mul OK
#1 unreachable OK
#2 unreachable2 OK
#3 out of range jump OK
#4 out of range jump2 OK
#5 test1 ld_imm64 OK
...
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-26 14:17:07 +07:00
|
|
|
return test();
|
|
|
|
}
|