Commit 6f1b5a2b authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'bpf-kselftest-improvements'

Daniel Borkmann says:

====================
First one unifies the often repeated rlimit handling and the
second one enables and adds run-time tests for BPF tail calls
which provides useful coverage in particular for JITs.
====================
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 3808b519 b33eb735
#include <sys/resource.h>
#include <stdio.h>
static __attribute__((constructor)) void bpf_rlimit_ctor(void)
{
struct rlimit rlim_old, rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
getrlimit(RLIMIT_MEMLOCK, &rlim_old);
/* For the sake of running the test cases, we temporarily
* set rlimit to infinity in order for kernel to focus on
* errors from actual test cases and not getting noise
* from hitting memlock limits. The limit is on per-process
* basis and not a global one, hence destructor not really
* needed here.
*/
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new) < 0) {
perror("Unable to lift memlock rlimit");
/* Trying out lower limit, but expect potential test
* case failures from this!
*/
rlim_new.rlim_cur = rlim_old.rlim_cur + (1UL << 20);
rlim_new.rlim_max = rlim_old.rlim_max + (1UL << 20);
setrlimit(RLIMIT_MEMLOCK, &rlim_new);
}
}
......@@ -9,8 +9,6 @@
#include <stddef.h>
#include <stdbool.h>
#include <sys/resource.h>
#include <linux/unistd.h>
#include <linux/filter.h>
#include <linux/bpf_perf_event.h>
......@@ -19,6 +17,7 @@
#include <bpf/bpf.h>
#include "../../../include/linux/filter.h"
#include "bpf_rlimit.h"
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
......@@ -702,9 +701,6 @@ static int do_test(unsigned int from, unsigned int to)
int main(int argc, char **argv)
{
unsigned int from = 0, to = ARRAY_SIZE(tests);
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
setrlimit(RLIMIT_MEMLOCK, &rinf);
if (argc == 3) {
unsigned int l = atoi(argv[argc - 2]);
......
......@@ -11,13 +11,13 @@
#include <errno.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <linux/bpf.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "cgroup_helpers.h"
#include "bpf_rlimit.h"
#define DEV_CGROUP_PROG "./dev_cgroup.o"
......@@ -25,15 +25,11 @@
int main(int argc, char **argv)
{
struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
struct bpf_object *obj;
int error = EXIT_FAILURE;
int prog_fd, cgroup_fd;
__u32 prog_cnt;
if (setrlimit(RLIMIT_MEMLOCK, &limit) < 0)
perror("Unable to lift memlock rlimit");
if (bpf_prog_load(DEV_CGROUP_PROG, BPF_PROG_TYPE_CGROUP_DEVICE,
&obj, &prog_fd)) {
printf("Failed to load DEV_CGROUP program\n");
......
......@@ -22,10 +22,11 @@
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <bpf/bpf.h>
#include "bpf_util.h"
#include "bpf_rlimit.h"
struct tlpm_node {
struct tlpm_node *next;
......@@ -736,17 +737,11 @@ static void test_lpm_multi_thread(void)
int main(void)
{
struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
int i, ret;
int i;
/* we want predictable, pseudo random tests */
srand(0xf00ba1);
/* allow unlimited locked memory */
ret = setrlimit(RLIMIT_MEMLOCK, &limit);
if (ret < 0)
perror("Unable to lift memlock rlimit");
test_lpm_basic();
test_lpm_order();
......@@ -755,11 +750,8 @@ int main(void)
test_lpm_map(i);
test_lpm_ipaddr();
test_lpm_delete();
test_lpm_get_next_key();
test_lpm_multi_thread();
printf("test_lpm: OK\n");
......
......@@ -16,10 +16,11 @@
#include <time.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <bpf/bpf.h>
#include "bpf_util.h"
#include "bpf_rlimit.h"
#define LOCAL_FREE_TARGET (128)
#define PERCPU_FREE_TARGET (4)
......@@ -613,7 +614,6 @@ static void test_lru_sanity6(int map_type, int map_flags, int tgt_free)
int main(int argc, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
int map_types[] = {BPF_MAP_TYPE_LRU_HASH,
BPF_MAP_TYPE_LRU_PERCPU_HASH};
int map_flags[] = {0, BPF_F_NO_COMMON_LRU};
......@@ -621,8 +621,6 @@ int main(int argc, char **argv)
setbuf(stdout, NULL);
assert(!setrlimit(RLIMIT_MEMLOCK, &r));
nr_cpus = bpf_num_possible_cpus();
assert(nr_cpus != -1);
printf("nr_cpus:%d\n\n", nr_cpus);
......
......@@ -17,13 +17,14 @@
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <linux/bpf.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "bpf_util.h"
#include "bpf_rlimit.h"
static int map_flags;
......@@ -1126,10 +1127,6 @@ static void run_all_tests(void)
int main(void)
{
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
setrlimit(RLIMIT_MEMLOCK, &rinf);
map_flags = 0;
run_all_tests();
......
......@@ -26,7 +26,6 @@ typedef __u16 __sum16;
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <fcntl.h>
......@@ -34,9 +33,11 @@ typedef __u16 __sum16;
#include <linux/err.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "test_iptunnel_common.h"
#include "bpf_util.h"
#include "bpf_endian.h"
#include "bpf_rlimit.h"
static int error_cnt, pass_cnt;
......@@ -965,10 +966,6 @@ static void test_stacktrace_map()
int main(void)
{
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
setrlimit(RLIMIT_MEMLOCK, &rinf);
test_pkt_access();
test_xdp();
test_l4lb_all();
......
......@@ -12,7 +12,6 @@
#include <assert.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <linux/filter.h>
#include <linux/bpf.h>
......@@ -21,6 +20,7 @@
#include <bpf/bpf.h>
#include "../../../include/linux/filter.h"
#include "bpf_rlimit.h"
static struct bpf_insn prog[BPF_MAXINSNS];
......@@ -184,11 +184,9 @@ static void do_test(uint32_t *tests, int start_insns, int fd_map,
int main(void)
{
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
uint32_t tests = 0;
int i, fd_map;
setrlimit(RLIMIT_MEMLOCK, &rinf);
fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int),
sizeof(int), 1, BPF_F_NO_PREALLOC);
assert(fd_map > 0);
......
......@@ -12,13 +12,13 @@
#include <linux/bpf.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "bpf_util.h"
#include "bpf_rlimit.h"
#include <linux/perf_event.h>
#include "test_tcpbpf.h"
......@@ -44,7 +44,6 @@ static int bpf_find_map(const char *test, struct bpf_object *obj,
int main(int argc, char **argv)
{
struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
const char *file = "test_tcpbpf_kern.o";
struct tcpbpf_globals g = {0};
int cg_fd, prog_fd, map_fd;
......@@ -57,9 +56,6 @@ int main(int argc, char **argv)
int pid;
int rv;
if (setrlimit(RLIMIT_MEMLOCK, &limit) < 0)
perror("Unable to lift memlock rlimit");
if (argc > 1 && strcmp(argv[1], "-d") == 0)
debug_flag = true;
......
......@@ -24,7 +24,6 @@
#include <limits.h>
#include <sys/capability.h>
#include <sys/resource.h>
#include <linux/unistd.h>
#include <linux/filter.h>
......@@ -41,7 +40,7 @@
# define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
# endif
#endif
#include "bpf_rlimit.h"
#include "../../../include/linux/filter.h"
#ifndef ARRAY_SIZE
......@@ -2589,6 +2588,62 @@ static struct bpf_test tests[] = {
.result_unpriv = REJECT,
.result = ACCEPT,
},
{
"runtime/jit: tail_call within bounds, prog once",
.insns = {
BPF_MOV64_IMM(BPF_REG_3, 0),
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, 1),
BPF_EXIT_INSN(),
},
.fixup_prog = { 1 },
.result = ACCEPT,
.retval = 42,
},
{
"runtime/jit: tail_call within bounds, prog loop",
.insns = {
BPF_MOV64_IMM(BPF_REG_3, 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, 1),
BPF_EXIT_INSN(),
},
.fixup_prog = { 1 },
.result = ACCEPT,
.retval = 41,
},
{
"runtime/jit: tail_call within bounds, no prog",
.insns = {
BPF_MOV64_IMM(BPF_REG_3, 2),
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, 1),
BPF_EXIT_INSN(),
},
.fixup_prog = { 1 },
.result = ACCEPT,
.retval = 1,
},
{
"runtime/jit: tail_call out of bounds",
.insns = {
BPF_MOV64_IMM(BPF_REG_3, 256),
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, 2),
BPF_EXIT_INSN(),
},
.fixup_prog = { 1 },
.result = ACCEPT,
.retval = 2,
},
{
"runtime/jit: pass negative index to tail_call",
.insns = {
......@@ -2596,11 +2651,12 @@ static struct bpf_test tests[] = {
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_MOV64_IMM(BPF_REG_0, 2),
BPF_EXIT_INSN(),
},
.fixup_prog = { 1 },
.result = ACCEPT,
.retval = 2,
},
{
"runtime/jit: pass > 32bit index to tail_call",
......@@ -2609,11 +2665,12 @@ static struct bpf_test tests[] = {
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_MOV64_IMM(BPF_REG_0, 2),
BPF_EXIT_INSN(),
},
.fixup_prog = { 2 },
.result = ACCEPT,
.retval = 42,
},
{
"stack pointer arithmetic",
......@@ -11279,16 +11336,61 @@ static int create_map(uint32_t size_value, uint32_t max_elem)
return fd;
}
static int create_prog_dummy1(void)
{
struct bpf_insn prog[] = {
BPF_MOV64_IMM(BPF_REG_0, 42),
BPF_EXIT_INSN(),
};
return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog,
ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
}
static int create_prog_dummy2(int mfd, int idx)
{
struct bpf_insn prog[] = {
BPF_MOV64_IMM(BPF_REG_3, idx),
BPF_LD_MAP_FD(BPF_REG_2, mfd),
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
BPF_FUNC_tail_call),
BPF_MOV64_IMM(BPF_REG_0, 41),
BPF_EXIT_INSN(),
};
return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog,
ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
}
static int create_prog_array(void)
{
int fd;
int p1key = 0, p2key = 1;
int mfd, p1fd, p2fd;
fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
sizeof(int), 4, 0);
if (fd < 0)
mfd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
sizeof(int), 4, 0);
if (mfd < 0) {
printf("Failed to create prog array '%s'!\n", strerror(errno));
return -1;
}
return fd;
p1fd = create_prog_dummy1();
p2fd = create_prog_dummy2(mfd, p2key);
if (p1fd < 0 || p2fd < 0)
goto out;
if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0)
goto out;
if (bpf_map_update_elem(mfd, &p2key, &p2fd, BPF_ANY) < 0)
goto out;
close(p2fd);
close(p1fd);
return mfd;
out:
close(p2fd);
close(p1fd);
close(mfd);
return -1;
}
static int create_map_in_map(void)
......@@ -11543,8 +11645,6 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to)
int main(int argc, char **argv)
{
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
struct rlimit rlim = { 1 << 20, 1 << 20 };
unsigned int from = 0, to = ARRAY_SIZE(tests);
bool unpriv = !is_admin();
......@@ -11572,6 +11672,5 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
setrlimit(RLIMIT_MEMLOCK, unpriv ? &rlim : &rinf);
return do_test(unpriv, from, to);
}
......@@ -4,7 +4,6 @@
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <linux/bpf.h>
#include <linux/filter.h>
......@@ -12,6 +11,8 @@
#include <bpf/bpf.h>
#include "bpf_rlimit.h"
#define LOG_SIZE (1 << 20)
#define err(str...) printf("ERROR: " str)
......@@ -133,16 +134,11 @@ static void test_log_bad(char *log, size_t log_len, int log_level)
int main(int argc, char **argv)
{
struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
char full_log[LOG_SIZE];
char log[LOG_SIZE];
size_t want_len;
int i;
/* allow unlimited locked memory to have more consistent error code */
if (setrlimit(RLIMIT_MEMLOCK, &limit) < 0)
perror("Unable to lift memlock rlimit");
memset(log, 1, LOG_SIZE);
/* Test incorrect attr */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment