diff --git a/tools/testing/selftests/bpf/bpf_rlimit.h b/tools/testing/selftests/bpf/bpf_rlimit.h new file mode 100644 index 0000000000000000000000000000000000000000..9dac9b30f8ef21151e4e55baf6d4e9554f60ca0a --- /dev/null +++ b/tools/testing/selftests/bpf/bpf_rlimit.h @@ -0,0 +1,28 @@ +#include +#include + +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); + } +} diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c index ff8bd7e3e50c19231f35233714e499d8b2504d24..6b1b302310feb6881629ecaab0911c79d6f32efd 100644 --- a/tools/testing/selftests/bpf/test_align.c +++ b/tools/testing/selftests/bpf/test_align.c @@ -9,8 +9,6 @@ #include #include -#include - #include #include #include @@ -19,6 +17,7 @@ #include #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]); diff --git a/tools/testing/selftests/bpf/test_dev_cgroup.c b/tools/testing/selftests/bpf/test_dev_cgroup.c index 3489cc28343351aa0e160a3d67f513eca65f843b..9c8b50bac7e01fd60dc436a5f986e384e2343b43 100644 --- a/tools/testing/selftests/bpf/test_dev_cgroup.c +++ b/tools/testing/selftests/bpf/test_dev_cgroup.c @@ -11,13 +11,13 @@ #include #include #include -#include #include #include #include #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"); diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/test_lpm_map.c index 2be87e9ee28d2c24594ff1d7540084e9dcf459d0..147e34cfceb79bef10672643c0ba265ccf68293d 100644 --- a/tools/testing/selftests/bpf/test_lpm_map.c +++ b/tools/testing/selftests/bpf/test_lpm_map.c @@ -22,10 +22,11 @@ #include #include #include -#include #include + #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"); diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c index 8c10c9180c1a6535f18caafcdf7195f69d04ecd2..781c7de343be005a92bffd7a2f6da0f0eaae22bb 100644 --- a/tools/testing/selftests/bpf/test_lru_map.c +++ b/tools/testing/selftests/bpf/test_lru_map.c @@ -16,10 +16,11 @@ #include #include -#include #include + #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); diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index 9e03a4c356a496e3f57d18058254df464c206278..1238733c5b33bceb33f6e59b74e03ba4137d93df 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c @@ -17,13 +17,14 @@ #include #include -#include #include #include #include + #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(); diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index b549308abd19860953bb063ad382f414ce8a3c45..27ad5404389e32a8e5d41abaf01f25b70f55dd1f 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -26,7 +26,6 @@ typedef __u16 __sum16; #include #include -#include #include #include @@ -34,9 +33,11 @@ typedef __u16 __sum16; #include #include #include + #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(); diff --git a/tools/testing/selftests/bpf/test_tag.c b/tools/testing/selftests/bpf/test_tag.c index 8b201895c569f9cf9cf5dc1af34cc3234bd7b4a2..6272c784ca2a4803dd4610db655aa7a36a172121 100644 --- a/tools/testing/selftests/bpf/test_tag.c +++ b/tools/testing/selftests/bpf/test_tag.c @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -21,6 +20,7 @@ #include #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); diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c index 5d73db4164607da6577444bfe03719e09954a9a9..84ab5163c8281211f606167cfc23ed152efa0fcb 100644 --- a/tools/testing/selftests/bpf/test_tcpbpf_user.c +++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c @@ -12,13 +12,13 @@ #include #include #include -#include #include #include #include #include #include #include "bpf_util.h" +#include "bpf_rlimit.h" #include #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; diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 2164d218322e69aa50c5cc75b801476191a4eec2..9eb05f3135ac92b964a4e512b4e3a7d58e00840f 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -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); } diff --git a/tools/testing/selftests/bpf/test_verifier_log.c b/tools/testing/selftests/bpf/test_verifier_log.c index e9626cf5607ad060b070680d25986a270c5cd59c..8d6918c3b4a2c60f6cf610aaaccaa7db1e66515f 100644 --- a/tools/testing/selftests/bpf/test_verifier_log.c +++ b/tools/testing/selftests/bpf/test_verifier_log.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -12,6 +11,8 @@ #include +#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 */