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 15:17:07 +08: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 02:57:43 +08:00
|
|
|
#include <stddef.h>
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
#include "libbpf.h"
|
|
|
|
|
|
|
|
#define MAX_INSNS 512
|
|
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
|
|
|
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
struct bpf_test {
|
|
|
|
const char *descr;
|
|
|
|
struct bpf_insn insns[MAX_INSNS];
|
2015-10-08 13:23:23 +08:00
|
|
|
int fixup[MAX_FIXUPS];
|
|
|
|
int prog_array_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 15:17:07 +08:00
|
|
|
const char *errstr;
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
enum {
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
ACCEPT,
|
|
|
|
REJECT
|
2015-10-08 13:23:23 +08:00
|
|
|
} result, result_unpriv;
|
2015-06-05 01:11:54 +08: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 15:17:07 +08: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 13:23:23 +08: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 15:17:07 +08: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 13:23:23 +08: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 15:17:07 +08: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 05:54:57 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2014-10-21 05:54:57 +08: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 15:17:07 +08: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 09:36:50 +08: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 15:17:07 +08: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,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"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 19:31:41 +08: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 15:17:07 +08:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
.result = ACCEPT,
|
2015-10-08 13:23:23 +08: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 15:17:07 +08: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 06:10:54 +08: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 15:17:07 +08: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 13:23:23 +08: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 15:17:07 +08: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 09:36:50 +08: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 15:17:07 +08: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 09:36:50 +08: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 15:17:07 +08: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 09:36:50 +08: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 15:17:07 +08: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 09:36:50 +08: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 15:17:07 +08: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 13:23:23 +08: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 15:17:07 +08:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
2014-09-30 09:50:02 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 09:50:02 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 09:50:02 +08: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 09:36:50 +08:00
|
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem),
|
2014-09-30 09:50:02 +08:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.fixup = {24},
|
2015-10-08 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 09:50:02 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-09-30 09:50:02 +08:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
2014-10-29 06:11:42 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
|
|
|
.result_unpriv = REJECT,
|
2014-10-29 06:11:42 +08:00
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
2015-03-14 02:57:43 +08: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 09:06:02 +08: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 02:57:43 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2015-03-14 02:57:43 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2015-03-14 02:57:43 +08:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
2015-04-16 07:19:33 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 pointer comparison",
|
2015-04-16 07:19:33 +08:00
|
|
|
.result = REJECT,
|
|
|
|
},
|
2015-06-05 01:11:54 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
2015-06-05 01:11:54 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
2015-06-05 01:11:54 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
2015-06-05 01:11:54 +08: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 13:23:23 +08:00
|
|
|
offsetof(struct __sk_buff, cb[0]) + 256),
|
2015-06-05 01:11:54 +08:00
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.errstr = "invalid bpf_context access",
|
2015-10-08 13:23:23 +08:00
|
|
|
.errstr_unpriv = "",
|
2015-06-05 01:11:54 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "R1 leaks addr",
|
|
|
|
.result_unpriv = REJECT,
|
2015-06-05 01:11:54 +08: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 13:23:23 +08:00
|
|
|
.errstr_unpriv = "",
|
|
|
|
.result_unpriv = REJECT,
|
2015-06-05 01:11:54 +08:00
|
|
|
.result = ACCEPT,
|
|
|
|
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
|
|
|
},
|
2015-07-24 05:24:40 +08: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 13:23:23 +08: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 06:10:54 +08: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,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"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 10:49:15 +08:00
|
|
|
{
|
|
|
|
"pkt: test1",
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pkt: test2",
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pkt: test3",
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pkt: test4",
|
|
|
|
.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(),
|
|
|
|
},
|
|
|
|
.errstr = "cannot write",
|
|
|
|
.result = REJECT,
|
|
|
|
.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 15:17:07 +08: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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int create_map(void)
|
|
|
|
{
|
|
|
|
int map_fd;
|
|
|
|
|
2015-10-08 13:23:23 +08:00
|
|
|
map_fd = bpf_create_map(BPF_MAP_TYPE_HASH,
|
2016-03-08 13:57:20 +08:00
|
|
|
sizeof(long long), sizeof(long long), 1024, 0);
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
printf("failed to create map '%s'\n", strerror(errno));
|
2015-10-08 13:23:23 +08: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 13:57:20 +08:00
|
|
|
sizeof(int), sizeof(int), 4, 0);
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
|
|
|
|
return map_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int test(void)
|
|
|
|
{
|
2014-10-29 06:11:42 +08:00
|
|
|
int prog_fd, i, pass_cnt = 0, err_cnt = 0;
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
|
|
|
struct bpf_insn *prog = tests[i].insns;
|
2015-06-05 01:11:54 +08: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 15:17:07 +08:00
|
|
|
int prog_len = probe_filter_length(prog);
|
|
|
|
int *fixup = tests[i].fixup;
|
2015-10-08 13:23:23 +08:00
|
|
|
int *prog_array_fixup = tests[i].prog_array_fixup;
|
|
|
|
int expected_result;
|
|
|
|
const char *expected_errstr;
|
|
|
|
int map_fd = -1, prog_array_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 15:17:07 +08:00
|
|
|
|
|
|
|
if (*fixup) {
|
|
|
|
map_fd = create_map();
|
|
|
|
|
|
|
|
do {
|
|
|
|
prog[*fixup].imm = map_fd;
|
|
|
|
fixup++;
|
|
|
|
} while (*fixup);
|
|
|
|
}
|
2015-10-08 13:23:23 +08: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);
|
|
|
|
}
|
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 15:17:07 +08:00
|
|
|
printf("#%d %s ", i, tests[i].descr);
|
|
|
|
|
2015-06-05 01:11:54 +08:00
|
|
|
prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
|
|
|
|
prog, prog_len * sizeof(struct bpf_insn),
|
2015-03-26 03:49:23 +08: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 15:17:07 +08:00
|
|
|
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
if (prog_fd < 0) {
|
|
|
|
printf("FAIL\nfailed to load prog '%s'\n",
|
|
|
|
strerror(errno));
|
|
|
|
printf("%s", bpf_log_buf);
|
2014-10-29 06:11:42 +08: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 15:17:07 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (prog_fd >= 0) {
|
|
|
|
printf("FAIL\nunexpected success to load\n");
|
|
|
|
printf("%s", bpf_log_buf);
|
2014-10-29 06:11:42 +08: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 15:17:07 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
printf("FAIL\nunexpected error message: %s",
|
|
|
|
bpf_log_buf);
|
2014-10-29 06:11:42 +08: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 15:17:07 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-29 06:11:42 +08: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 15:17:07 +08:00
|
|
|
printf("OK\n");
|
|
|
|
fail:
|
|
|
|
if (map_fd >= 0)
|
|
|
|
close(map_fd);
|
2015-10-08 13:23:23 +08:00
|
|
|
if (prog_array_fd >= 0)
|
|
|
|
close(prog_array_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 15:17:07 +08:00
|
|
|
close(prog_fd);
|
|
|
|
|
|
|
|
}
|
2014-10-29 06:11:42 +08: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 15:17:07 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
2015-10-08 13:23:23 +08: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 15:17:07 +08:00
|
|
|
return test();
|
|
|
|
}
|