125763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 25aa5bd14SDaniel Borkmann /* 35aa5bd14SDaniel Borkmann * Testsuite for eBPF verifier 45aa5bd14SDaniel Borkmann * 55aa5bd14SDaniel Borkmann * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 6a7ff3ecaSAlexei Starovoitov * Copyright (c) 2017 Facebook 7b584ab88SJoe Stringer * Copyright (c) 2018 Covalent IO, Inc. http://covalent.io 85aa5bd14SDaniel Borkmann */ 95aa5bd14SDaniel Borkmann 102c460621SDaniel Borkmann #include <endian.h> 111da8ac7cSAlexei Starovoitov #include <asm/types.h> 121da8ac7cSAlexei Starovoitov #include <linux/types.h> 13702498a1SMickaël Salaün #include <stdint.h> 145aa5bd14SDaniel Borkmann #include <stdio.h> 15702498a1SMickaël Salaün #include <stdlib.h> 165aa5bd14SDaniel Borkmann #include <unistd.h> 175aa5bd14SDaniel Borkmann #include <errno.h> 185aa5bd14SDaniel Borkmann #include <string.h> 195aa5bd14SDaniel Borkmann #include <stddef.h> 205aa5bd14SDaniel Borkmann #include <stdbool.h> 215aa5bd14SDaniel Borkmann #include <sched.h> 2221ccaf21SDaniel Borkmann #include <limits.h> 2380c9b2faSDaniel Borkmann #include <assert.h> 245aa5bd14SDaniel Borkmann 255aa5bd14SDaniel Borkmann #include <linux/unistd.h> 265aa5bd14SDaniel Borkmann #include <linux/filter.h> 275aa5bd14SDaniel Borkmann #include <linux/bpf_perf_event.h> 285aa5bd14SDaniel Borkmann #include <linux/bpf.h> 29111e6b45SAlexei Starovoitov #include <linux/if_ether.h> 30b4d4556cSAlexei Starovoitov #include <linux/btf.h> 315aa5bd14SDaniel Borkmann 320201b807SKumar Kartikeya Dwivedi #include <bpf/btf.h> 332ee89fb9SMickaël Salaün #include <bpf/bpf.h> 348184d44cSStanislav Fomichev #include <bpf/libbpf.h> 352ee89fb9SMickaël Salaün 3602ea80b1SDaniel Borkmann #ifdef HAVE_GENHDR 3702ea80b1SDaniel Borkmann # include "autoconf.h" 3802ea80b1SDaniel Borkmann #else 3902ea80b1SDaniel Borkmann # if defined(__i386) || defined(__x86_64) || defined(__s390x__) || defined(__aarch64__) 4002ea80b1SDaniel Borkmann # define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1 4102ea80b1SDaniel Borkmann # endif 4202ea80b1SDaniel Borkmann #endif 43b1c2768aSMartin KaFai Lau #include "cap_helpers.h" 44a82d8cd3SDaniel Borkmann #include "bpf_rand.h" 45aa5f0c96SMartin KaFai Lau #include "bpf_util.h" 467a9bb976SMartin KaFai Lau #include "test_btf.h" 475aa5bd14SDaniel Borkmann #include "../../../include/linux/filter.h" 485aa5bd14SDaniel Borkmann 495319255bSIlya Leoshkevich #ifndef ENOTSUPP 505319255bSIlya Leoshkevich #define ENOTSUPP 524 515319255bSIlya Leoshkevich #endif 525319255bSIlya Leoshkevich 5393731ef0SDaniel Borkmann #define MAX_INSNS BPF_MAXINSNS 54933ff531SEduard Zingerman #define MAX_EXPECTED_INSNS 32 55933ff531SEduard Zingerman #define MAX_UNEXPECTED_INSNS 32 568aa2d4b4SAlexei Starovoitov #define MAX_TEST_INSNS 1000000 575aa5bd14SDaniel Borkmann #define MAX_FIXUPS 8 5805a945deSKumar Kartikeya Dwivedi #define MAX_NR_MAPS 23 595a8d5209SJakub Kicinski #define MAX_TEST_RUNS 8 60111e6b45SAlexei Starovoitov #define POINTER_VALUE 0xcafe4all 61111e6b45SAlexei Starovoitov #define TEST_DATA_LEN 64 627a42008cSEduard Zingerman #define MAX_FUNC_INFOS 8 637a42008cSEduard Zingerman #define MAX_BTF_STRINGS 256 647a42008cSEduard Zingerman #define MAX_BTF_TYPES 256 655aa5bd14SDaniel Borkmann 66933ff531SEduard Zingerman #define INSN_OFF_MASK ((__s16)0xFFFF) 67933ff531SEduard Zingerman #define INSN_IMM_MASK ((__s32)0xFFFFFFFF) 68933ff531SEduard Zingerman #define SKIP_INSNS() BPF_RAW_INSN(0xde, 0xa, 0xd, 0xbeef, 0xdeadbeef) 69933ff531SEduard Zingerman 707a42008cSEduard Zingerman #define DEFAULT_LIBBPF_LOG_LEVEL 4 717a42008cSEduard Zingerman 7202ea80b1SDaniel Borkmann #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) 73614d0d77SDaniel Borkmann #define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) 7402ea80b1SDaniel Borkmann 75b1c2768aSMartin KaFai Lau /* need CAP_BPF, CAP_NET_ADMIN, CAP_PERFMON to load progs */ 76b1c2768aSMartin KaFai Lau #define ADMIN_CAPS (1ULL << CAP_NET_ADMIN | \ 77b1c2768aSMartin KaFai Lau 1ULL << CAP_PERFMON | \ 78b1c2768aSMartin KaFai Lau 1ULL << CAP_BPF) 790a674874SJoe Stringer #define UNPRIV_SYSCTL "kernel/unprivileged_bpf_disabled" 800a674874SJoe Stringer static bool unpriv_disabled = false; 818184d44cSStanislav Fomichev static int skips; 82e8c13c4dSAlexei Starovoitov static bool verbose = false; 832a72f595SAndrii Nakryiko static int verif_log_level = 0; 840a674874SJoe Stringer 850201b807SKumar Kartikeya Dwivedi struct kfunc_btf_id_pair { 860201b807SKumar Kartikeya Dwivedi const char *kfunc; 870201b807SKumar Kartikeya Dwivedi int insn_idx; 880201b807SKumar Kartikeya Dwivedi }; 890201b807SKumar Kartikeya Dwivedi 905aa5bd14SDaniel Borkmann struct bpf_test { 915aa5bd14SDaniel Borkmann const char *descr; 925aa5bd14SDaniel Borkmann struct bpf_insn insns[MAX_INSNS]; 938aa2d4b4SAlexei Starovoitov struct bpf_insn *fill_insns; 94933ff531SEduard Zingerman /* If specified, test engine looks for this sequence of 95933ff531SEduard Zingerman * instructions in the BPF program after loading. Allows to 96933ff531SEduard Zingerman * test rewrites applied by verifier. Use values 97933ff531SEduard Zingerman * INSN_OFF_MASK and INSN_IMM_MASK to mask `off` and `imm` 98933ff531SEduard Zingerman * fields if content does not matter. The test case fails if 99933ff531SEduard Zingerman * specified instructions are not found. 100933ff531SEduard Zingerman * 101933ff531SEduard Zingerman * The sequence could be split into sub-sequences by adding 102933ff531SEduard Zingerman * SKIP_INSNS instruction at the end of each sub-sequence. In 103933ff531SEduard Zingerman * such case sub-sequences are searched for one after another. 104933ff531SEduard Zingerman */ 105933ff531SEduard Zingerman struct bpf_insn expected_insns[MAX_EXPECTED_INSNS]; 106933ff531SEduard Zingerman /* If specified, test engine applies same pattern matching 107933ff531SEduard Zingerman * logic as for `expected_insns`. If the specified pattern is 108933ff531SEduard Zingerman * matched test case is marked as failed. 109933ff531SEduard Zingerman */ 110933ff531SEduard Zingerman struct bpf_insn unexpected_insns[MAX_UNEXPECTED_INSNS]; 111908142e6SPrashant Bhole int fixup_map_hash_8b[MAX_FIXUPS]; 112908142e6SPrashant Bhole int fixup_map_hash_48b[MAX_FIXUPS]; 113908142e6SPrashant Bhole int fixup_map_hash_16b[MAX_FIXUPS]; 114908142e6SPrashant Bhole int fixup_map_array_48b[MAX_FIXUPS]; 1157c85c448SPrashant Bhole int fixup_map_sockmap[MAX_FIXUPS]; 1167c85c448SPrashant Bhole int fixup_map_sockhash[MAX_FIXUPS]; 1177c85c448SPrashant Bhole int fixup_map_xskmap[MAX_FIXUPS]; 1187c85c448SPrashant Bhole int fixup_map_stacktrace[MAX_FIXUPS]; 11906be0864SDaniel Borkmann int fixup_prog1[MAX_FIXUPS]; 12006be0864SDaniel Borkmann int fixup_prog2[MAX_FIXUPS]; 121fb30d4b7SMartin KaFai Lau int fixup_map_in_map[MAX_FIXUPS]; 122d4c9f573SRoman Gushchin int fixup_cgroup_storage[MAX_FIXUPS]; 123a3c6054fSRoman Gushchin int fixup_percpu_cgroup_storage[MAX_FIXUPS]; 124b4d4556cSAlexei Starovoitov int fixup_map_spin_lock[MAX_FIXUPS]; 125fb2abb73SDaniel Borkmann int fixup_map_array_ro[MAX_FIXUPS]; 126fb2abb73SDaniel Borkmann int fixup_map_array_wo[MAX_FIXUPS]; 127fb2abb73SDaniel Borkmann int fixup_map_array_small[MAX_FIXUPS]; 1287a9bb976SMartin KaFai Lau int fixup_sk_storage_map[MAX_FIXUPS]; 12903cd1d1aSAllan Zhang int fixup_map_event_output[MAX_FIXUPS]; 130c3210222SJakub Sitnicki int fixup_map_reuseport_array[MAX_FIXUPS]; 1314237e9f4SGilad Reti int fixup_map_ringbuf[MAX_FIXUPS]; 132e60e6962SDmitrii Banshchikov int fixup_map_timer[MAX_FIXUPS]; 13305a945deSKumar Kartikeya Dwivedi int fixup_map_kptr[MAX_FIXUPS]; 1340201b807SKumar Kartikeya Dwivedi struct kfunc_btf_id_pair fixup_kfunc_btf_id[MAX_FIXUPS]; 135060fd103SAndrei Matei /* Expected verifier log output for result REJECT or VERBOSE_ACCEPT. 136060fd103SAndrei Matei * Can be a tab-separated sequence of expected strings. An empty string 137060fd103SAndrei Matei * means no log verification. 138060fd103SAndrei Matei */ 1395aa5bd14SDaniel Borkmann const char *errstr; 1405aa5bd14SDaniel Borkmann const char *errstr_unpriv; 141d5e1db99SAndrii Nakryiko uint32_t insn_processed; 1428aa2d4b4SAlexei Starovoitov int prog_len; 1435aa5bd14SDaniel Borkmann enum { 1445aa5bd14SDaniel Borkmann UNDEF, 1455aa5bd14SDaniel Borkmann ACCEPT, 146e8c13c4dSAlexei Starovoitov REJECT, 147e8c13c4dSAlexei Starovoitov VERBOSE_ACCEPT, 1485aa5bd14SDaniel Borkmann } result, result_unpriv; 1495aa5bd14SDaniel Borkmann enum bpf_prog_type prog_type; 15002ea80b1SDaniel Borkmann uint8_t flags; 15193731ef0SDaniel Borkmann void (*fill_helper)(struct bpf_test *self); 152b4f89463SLorenz Bauer int runs; 153d5e1db99SAndrii Nakryiko #define bpf_testdata_struct_t \ 154d5e1db99SAndrii Nakryiko struct { \ 155d5e1db99SAndrii Nakryiko uint32_t retval, retval_unpriv; \ 156d5e1db99SAndrii Nakryiko union { \ 157d5e1db99SAndrii Nakryiko __u8 data[TEST_DATA_LEN]; \ 158d5e1db99SAndrii Nakryiko __u64 data64[TEST_DATA_LEN / 8]; \ 159d5e1db99SAndrii Nakryiko }; \ 160d5e1db99SAndrii Nakryiko } 1615a8d5209SJakub Kicinski union { 162d5e1db99SAndrii Nakryiko bpf_testdata_struct_t; 163d5e1db99SAndrii Nakryiko bpf_testdata_struct_t retvals[MAX_TEST_RUNS]; 1645a8d5209SJakub Kicinski }; 16576d95077SStanislav Fomichev enum bpf_attach_type expected_attach_type; 166762f8515SJiri Olsa const char *kfunc; 1677a42008cSEduard Zingerman struct bpf_func_info func_info[MAX_FUNC_INFOS]; 1687a42008cSEduard Zingerman int func_info_cnt; 1697a42008cSEduard Zingerman char btf_strings[MAX_BTF_STRINGS]; 1707a42008cSEduard Zingerman /* A set of BTF types to load when specified, 1717a42008cSEduard Zingerman * use macro definitions from test_btf.h, 1727a42008cSEduard Zingerman * must end with BTF_END_RAW 1737a42008cSEduard Zingerman */ 1747a42008cSEduard Zingerman __u32 btf_types[MAX_BTF_TYPES]; 1755aa5bd14SDaniel Borkmann }; 1765aa5bd14SDaniel Borkmann 1775aa5bd14SDaniel Borkmann /* Note we want this to be 64 bit aligned so that the end of our array is 1785aa5bd14SDaniel Borkmann * actually the end of the structure. 1795aa5bd14SDaniel Borkmann */ 1805aa5bd14SDaniel Borkmann #define MAX_ENTRIES 11 1815aa5bd14SDaniel Borkmann 1825aa5bd14SDaniel Borkmann struct test_val { 1835aa5bd14SDaniel Borkmann unsigned int index; 1845aa5bd14SDaniel Borkmann int foo[MAX_ENTRIES]; 1855aa5bd14SDaniel Borkmann }; 1865aa5bd14SDaniel Borkmann 1875f90dd6aSPaul Chaignon struct other_val { 1885f90dd6aSPaul Chaignon long long foo; 1895f90dd6aSPaul Chaignon long long bar; 1905f90dd6aSPaul Chaignon }; 1915f90dd6aSPaul Chaignon 19293731ef0SDaniel Borkmann static void bpf_fill_ld_abs_vlan_push_pop(struct bpf_test *self) 19393731ef0SDaniel Borkmann { 1948aa2d4b4SAlexei Starovoitov /* test: {skb->data[0], vlan_push} x 51 + {skb->data[0], vlan_pop} x 51 */ 19593731ef0SDaniel Borkmann #define PUSH_CNT 51 1968aa2d4b4SAlexei Starovoitov /* jump range is limited to 16 bit. PUSH_CNT of ld_abs needs room */ 1978aa2d4b4SAlexei Starovoitov unsigned int len = (1 << 15) - PUSH_CNT * 2 * 5 * 6; 1988aa2d4b4SAlexei Starovoitov struct bpf_insn *insn = self->fill_insns; 19993731ef0SDaniel Borkmann int i = 0, j, k = 0; 20093731ef0SDaniel Borkmann 20193731ef0SDaniel Borkmann insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); 20293731ef0SDaniel Borkmann loop: 20393731ef0SDaniel Borkmann for (j = 0; j < PUSH_CNT; j++) { 20493731ef0SDaniel Borkmann insn[i++] = BPF_LD_ABS(BPF_B, 0); 205f3b55abbSJiong Wang /* jump to error label */ 206f3b55abbSJiong Wang insn[i] = BPF_JMP32_IMM(BPF_JNE, BPF_REG_0, 0x34, len - i - 3); 20793731ef0SDaniel Borkmann i++; 20893731ef0SDaniel Borkmann insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6); 20993731ef0SDaniel Borkmann insn[i++] = BPF_MOV64_IMM(BPF_REG_2, 1); 21093731ef0SDaniel Borkmann insn[i++] = BPF_MOV64_IMM(BPF_REG_3, 2); 21193731ef0SDaniel Borkmann insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 21215080908STiezhu Yang BPF_FUNC_skb_vlan_push); 213f3b55abbSJiong Wang insn[i] = BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, len - i - 3); 21493731ef0SDaniel Borkmann i++; 21593731ef0SDaniel Borkmann } 21693731ef0SDaniel Borkmann 21793731ef0SDaniel Borkmann for (j = 0; j < PUSH_CNT; j++) { 21893731ef0SDaniel Borkmann insn[i++] = BPF_LD_ABS(BPF_B, 0); 219f3b55abbSJiong Wang insn[i] = BPF_JMP32_IMM(BPF_JNE, BPF_REG_0, 0x34, len - i - 3); 22093731ef0SDaniel Borkmann i++; 22193731ef0SDaniel Borkmann insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6); 22293731ef0SDaniel Borkmann insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 22315080908STiezhu Yang BPF_FUNC_skb_vlan_pop); 224f3b55abbSJiong Wang insn[i] = BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, len - i - 3); 22593731ef0SDaniel Borkmann i++; 22693731ef0SDaniel Borkmann } 22793731ef0SDaniel Borkmann if (++k < 5) 22893731ef0SDaniel Borkmann goto loop; 22993731ef0SDaniel Borkmann 230f3b55abbSJiong Wang for (; i < len - 3; i++) 231f3b55abbSJiong Wang insn[i] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0xbef); 232f3b55abbSJiong Wang insn[len - 3] = BPF_JMP_A(1); 233f3b55abbSJiong Wang /* error label */ 234f3b55abbSJiong Wang insn[len - 2] = BPF_MOV32_IMM(BPF_REG_0, 0); 23593731ef0SDaniel Borkmann insn[len - 1] = BPF_EXIT_INSN(); 2368aa2d4b4SAlexei Starovoitov self->prog_len = len; 23793731ef0SDaniel Borkmann } 23893731ef0SDaniel Borkmann 23993731ef0SDaniel Borkmann static void bpf_fill_jump_around_ld_abs(struct bpf_test *self) 24093731ef0SDaniel Borkmann { 2418aa2d4b4SAlexei Starovoitov struct bpf_insn *insn = self->fill_insns; 242f3b55abbSJiong Wang /* jump range is limited to 16 bit. every ld_abs is replaced by 6 insns, 243f3b55abbSJiong Wang * but on arches like arm, ppc etc, there will be one BPF_ZEXT inserted 244f3b55abbSJiong Wang * to extend the error value of the inlined ld_abs sequence which then 245f3b55abbSJiong Wang * contains 7 insns. so, set the dividend to 7 so the testcase could 246f3b55abbSJiong Wang * work on all arches. 247f3b55abbSJiong Wang */ 248f3b55abbSJiong Wang unsigned int len = (1 << 15) / 7; 24993731ef0SDaniel Borkmann int i = 0; 25093731ef0SDaniel Borkmann 25193731ef0SDaniel Borkmann insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); 25293731ef0SDaniel Borkmann insn[i++] = BPF_LD_ABS(BPF_B, 0); 25393731ef0SDaniel Borkmann insn[i] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 10, len - i - 2); 25493731ef0SDaniel Borkmann i++; 25593731ef0SDaniel Borkmann while (i < len - 1) 25693731ef0SDaniel Borkmann insn[i++] = BPF_LD_ABS(BPF_B, 1); 25793731ef0SDaniel Borkmann insn[i] = BPF_EXIT_INSN(); 2588aa2d4b4SAlexei Starovoitov self->prog_len = i + 1; 25993731ef0SDaniel Borkmann } 26093731ef0SDaniel Borkmann 261a82d8cd3SDaniel Borkmann static void bpf_fill_rand_ld_dw(struct bpf_test *self) 262a82d8cd3SDaniel Borkmann { 2638aa2d4b4SAlexei Starovoitov struct bpf_insn *insn = self->fill_insns; 264a82d8cd3SDaniel Borkmann uint64_t res = 0; 265a82d8cd3SDaniel Borkmann int i = 0; 266a82d8cd3SDaniel Borkmann 267a82d8cd3SDaniel Borkmann insn[i++] = BPF_MOV32_IMM(BPF_REG_0, 0); 268a82d8cd3SDaniel Borkmann while (i < self->retval) { 269a82d8cd3SDaniel Borkmann uint64_t val = bpf_semi_rand_get(); 270a82d8cd3SDaniel Borkmann struct bpf_insn tmp[2] = { BPF_LD_IMM64(BPF_REG_1, val) }; 271a82d8cd3SDaniel Borkmann 272a82d8cd3SDaniel Borkmann res ^= val; 273a82d8cd3SDaniel Borkmann insn[i++] = tmp[0]; 274a82d8cd3SDaniel Borkmann insn[i++] = tmp[1]; 275a82d8cd3SDaniel Borkmann insn[i++] = BPF_ALU64_REG(BPF_XOR, BPF_REG_0, BPF_REG_1); 276a82d8cd3SDaniel Borkmann } 277a82d8cd3SDaniel Borkmann insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_0); 278a82d8cd3SDaniel Borkmann insn[i++] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 32); 279a82d8cd3SDaniel Borkmann insn[i++] = BPF_ALU64_REG(BPF_XOR, BPF_REG_0, BPF_REG_1); 280a82d8cd3SDaniel Borkmann insn[i] = BPF_EXIT_INSN(); 2818aa2d4b4SAlexei Starovoitov self->prog_len = i + 1; 282a82d8cd3SDaniel Borkmann res ^= (res >> 32); 283a82d8cd3SDaniel Borkmann self->retval = (uint32_t)res; 284a82d8cd3SDaniel Borkmann } 285a82d8cd3SDaniel Borkmann 2867c0c6095SAlexei Starovoitov #define MAX_JMP_SEQ 8192 2877c0c6095SAlexei Starovoitov 2887c0c6095SAlexei Starovoitov /* test the sequence of 8k jumps */ 28908de198cSAlexei Starovoitov static void bpf_fill_scale1(struct bpf_test *self) 29008de198cSAlexei Starovoitov { 29108de198cSAlexei Starovoitov struct bpf_insn *insn = self->fill_insns; 29208de198cSAlexei Starovoitov int i = 0, k = 0; 29308de198cSAlexei Starovoitov 29408de198cSAlexei Starovoitov insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); 2957c0c6095SAlexei Starovoitov /* test to check that the long sequence of jumps is acceptable */ 2967c0c6095SAlexei Starovoitov while (k++ < MAX_JMP_SEQ) { 29708de198cSAlexei Starovoitov insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 29808de198cSAlexei Starovoitov BPF_FUNC_get_prandom_u32); 2997c0c6095SAlexei Starovoitov insn[i++] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, bpf_semi_rand_get(), 2); 30008de198cSAlexei Starovoitov insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_10); 30108de198cSAlexei Starovoitov insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 30208de198cSAlexei Starovoitov -8 * (k % 64 + 1)); 30308de198cSAlexei Starovoitov } 304aeee380cSAlexei Starovoitov /* is_state_visited() doesn't allocate state for pruning for every jump. 305aeee380cSAlexei Starovoitov * Hence multiply jmps by 4 to accommodate that heuristic 30608de198cSAlexei Starovoitov */ 307aeee380cSAlexei Starovoitov while (i < MAX_TEST_INSNS - MAX_JMP_SEQ * 4) 308f3b55abbSJiong Wang insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 42); 30908de198cSAlexei Starovoitov insn[i] = BPF_EXIT_INSN(); 31008de198cSAlexei Starovoitov self->prog_len = i + 1; 31108de198cSAlexei Starovoitov self->retval = 42; 31208de198cSAlexei Starovoitov } 31308de198cSAlexei Starovoitov 3147c0c6095SAlexei Starovoitov /* test the sequence of 8k jumps in inner most function (function depth 8)*/ 31508de198cSAlexei Starovoitov static void bpf_fill_scale2(struct bpf_test *self) 31608de198cSAlexei Starovoitov { 31708de198cSAlexei Starovoitov struct bpf_insn *insn = self->fill_insns; 31808de198cSAlexei Starovoitov int i = 0, k = 0; 31908de198cSAlexei Starovoitov 32008de198cSAlexei Starovoitov #define FUNC_NEST 7 32108de198cSAlexei Starovoitov for (k = 0; k < FUNC_NEST; k++) { 32208de198cSAlexei Starovoitov insn[i++] = BPF_CALL_REL(1); 32308de198cSAlexei Starovoitov insn[i++] = BPF_EXIT_INSN(); 32408de198cSAlexei Starovoitov } 32508de198cSAlexei Starovoitov insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1); 3267c0c6095SAlexei Starovoitov /* test to check that the long sequence of jumps is acceptable */ 3277c0c6095SAlexei Starovoitov k = 0; 3287c0c6095SAlexei Starovoitov while (k++ < MAX_JMP_SEQ) { 32908de198cSAlexei Starovoitov insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 33008de198cSAlexei Starovoitov BPF_FUNC_get_prandom_u32); 3317c0c6095SAlexei Starovoitov insn[i++] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, bpf_semi_rand_get(), 2); 33208de198cSAlexei Starovoitov insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_10); 33308de198cSAlexei Starovoitov insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 33408de198cSAlexei Starovoitov -8 * (k % (64 - 4 * FUNC_NEST) + 1)); 33508de198cSAlexei Starovoitov } 336aeee380cSAlexei Starovoitov while (i < MAX_TEST_INSNS - MAX_JMP_SEQ * 4) 337f3b55abbSJiong Wang insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 42); 33808de198cSAlexei Starovoitov insn[i] = BPF_EXIT_INSN(); 33908de198cSAlexei Starovoitov self->prog_len = i + 1; 34008de198cSAlexei Starovoitov self->retval = 42; 34108de198cSAlexei Starovoitov } 34208de198cSAlexei Starovoitov 34308de198cSAlexei Starovoitov static void bpf_fill_scale(struct bpf_test *self) 34408de198cSAlexei Starovoitov { 34508de198cSAlexei Starovoitov switch (self->retval) { 34608de198cSAlexei Starovoitov case 1: 34708de198cSAlexei Starovoitov return bpf_fill_scale1(self); 34808de198cSAlexei Starovoitov case 2: 34908de198cSAlexei Starovoitov return bpf_fill_scale2(self); 35008de198cSAlexei Starovoitov default: 35108de198cSAlexei Starovoitov self->prog_len = 0; 35208de198cSAlexei Starovoitov break; 35308de198cSAlexei Starovoitov } 35408de198cSAlexei Starovoitov } 35508de198cSAlexei Starovoitov 35679d1b684SGary Lin static int bpf_fill_torturous_jumps_insn_1(struct bpf_insn *insn) 35779d1b684SGary Lin { 35879d1b684SGary Lin unsigned int len = 259, hlen = 128; 35979d1b684SGary Lin int i; 36079d1b684SGary Lin 36179d1b684SGary Lin insn[0] = BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32); 36279d1b684SGary Lin for (i = 1; i <= hlen; i++) { 36379d1b684SGary Lin insn[i] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, i, hlen); 36479d1b684SGary Lin insn[i + hlen] = BPF_JMP_A(hlen - i); 36579d1b684SGary Lin } 36679d1b684SGary Lin insn[len - 2] = BPF_MOV64_IMM(BPF_REG_0, 1); 36779d1b684SGary Lin insn[len - 1] = BPF_EXIT_INSN(); 36879d1b684SGary Lin 36979d1b684SGary Lin return len; 37079d1b684SGary Lin } 37179d1b684SGary Lin 37279d1b684SGary Lin static int bpf_fill_torturous_jumps_insn_2(struct bpf_insn *insn) 37379d1b684SGary Lin { 37479d1b684SGary Lin unsigned int len = 4100, jmp_off = 2048; 37579d1b684SGary Lin int i, j; 37679d1b684SGary Lin 37779d1b684SGary Lin insn[0] = BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32); 37879d1b684SGary Lin for (i = 1; i <= jmp_off; i++) { 37979d1b684SGary Lin insn[i] = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, i, jmp_off); 38079d1b684SGary Lin } 38179d1b684SGary Lin insn[i++] = BPF_JMP_A(jmp_off); 38279d1b684SGary Lin for (; i <= jmp_off * 2 + 1; i+=16) { 38379d1b684SGary Lin for (j = 0; j < 16; j++) { 38479d1b684SGary Lin insn[i + j] = BPF_JMP_A(16 - j - 1); 38579d1b684SGary Lin } 38679d1b684SGary Lin } 38779d1b684SGary Lin 38879d1b684SGary Lin insn[len - 2] = BPF_MOV64_IMM(BPF_REG_0, 2); 38979d1b684SGary Lin insn[len - 1] = BPF_EXIT_INSN(); 39079d1b684SGary Lin 39179d1b684SGary Lin return len; 39279d1b684SGary Lin } 39379d1b684SGary Lin 39479d1b684SGary Lin static void bpf_fill_torturous_jumps(struct bpf_test *self) 39579d1b684SGary Lin { 39679d1b684SGary Lin struct bpf_insn *insn = self->fill_insns; 39779d1b684SGary Lin int i = 0; 39879d1b684SGary Lin 39979d1b684SGary Lin switch (self->retval) { 40079d1b684SGary Lin case 1: 40179d1b684SGary Lin self->prog_len = bpf_fill_torturous_jumps_insn_1(insn); 40279d1b684SGary Lin return; 40379d1b684SGary Lin case 2: 40479d1b684SGary Lin self->prog_len = bpf_fill_torturous_jumps_insn_2(insn); 40579d1b684SGary Lin return; 40679d1b684SGary Lin case 3: 40779d1b684SGary Lin /* main */ 40879d1b684SGary Lin insn[i++] = BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 4); 40979d1b684SGary Lin insn[i++] = BPF_RAW_INSN(BPF_JMP|BPF_CALL, 0, 1, 0, 262); 41079d1b684SGary Lin insn[i++] = BPF_ST_MEM(BPF_B, BPF_REG_10, -32, 0); 41179d1b684SGary Lin insn[i++] = BPF_MOV64_IMM(BPF_REG_0, 3); 41279d1b684SGary Lin insn[i++] = BPF_EXIT_INSN(); 41379d1b684SGary Lin 41479d1b684SGary Lin /* subprog 1 */ 41579d1b684SGary Lin i += bpf_fill_torturous_jumps_insn_1(insn + i); 41679d1b684SGary Lin 41779d1b684SGary Lin /* subprog 2 */ 41879d1b684SGary Lin i += bpf_fill_torturous_jumps_insn_2(insn + i); 41979d1b684SGary Lin 42079d1b684SGary Lin self->prog_len = i; 42179d1b684SGary Lin return; 42279d1b684SGary Lin default: 42379d1b684SGary Lin self->prog_len = 0; 42479d1b684SGary Lin break; 42579d1b684SGary Lin } 42679d1b684SGary Lin } 42779d1b684SGary Lin 42841188e9eSEduard Zingerman static void bpf_fill_big_prog_with_loop_1(struct bpf_test *self) 42941188e9eSEduard Zingerman { 43041188e9eSEduard Zingerman struct bpf_insn *insn = self->fill_insns; 43141188e9eSEduard Zingerman /* This test was added to catch a specific use after free 43241188e9eSEduard Zingerman * error, which happened upon BPF program reallocation. 43341188e9eSEduard Zingerman * Reallocation is handled by core.c:bpf_prog_realloc, which 43441188e9eSEduard Zingerman * reuses old memory if page boundary is not crossed. The 43541188e9eSEduard Zingerman * value of `len` is chosen to cross this boundary on bpf_loop 43641188e9eSEduard Zingerman * patching. 43741188e9eSEduard Zingerman */ 43841188e9eSEduard Zingerman const int len = getpagesize() - 25; 43941188e9eSEduard Zingerman int callback_load_idx; 44041188e9eSEduard Zingerman int callback_idx; 44141188e9eSEduard Zingerman int i = 0; 44241188e9eSEduard Zingerman 44341188e9eSEduard Zingerman insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1); 44441188e9eSEduard Zingerman callback_load_idx = i; 44541188e9eSEduard Zingerman insn[i++] = BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 44641188e9eSEduard Zingerman BPF_REG_2, BPF_PSEUDO_FUNC, 0, 44741188e9eSEduard Zingerman 777 /* filled below */); 44841188e9eSEduard Zingerman insn[i++] = BPF_RAW_INSN(0, 0, 0, 0, 0); 44941188e9eSEduard Zingerman insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0); 45041188e9eSEduard Zingerman insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0); 45141188e9eSEduard Zingerman insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop); 45241188e9eSEduard Zingerman 45341188e9eSEduard Zingerman while (i < len - 3) 45441188e9eSEduard Zingerman insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0); 45541188e9eSEduard Zingerman insn[i++] = BPF_EXIT_INSN(); 45641188e9eSEduard Zingerman 45741188e9eSEduard Zingerman callback_idx = i; 45841188e9eSEduard Zingerman insn[i++] = BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0); 45941188e9eSEduard Zingerman insn[i++] = BPF_EXIT_INSN(); 46041188e9eSEduard Zingerman 46141188e9eSEduard Zingerman insn[callback_load_idx].imm = callback_idx - callback_load_idx - 1; 46241188e9eSEduard Zingerman self->func_info[1].insn_off = callback_idx; 46341188e9eSEduard Zingerman self->prog_len = i; 46441188e9eSEduard Zingerman assert(i == len); 46541188e9eSEduard Zingerman } 46641188e9eSEduard Zingerman 467b584ab88SJoe Stringer /* BPF_SK_LOOKUP contains 13 instructions, if you need to fix up maps */ 468dbaf2877SLorenz Bauer #define BPF_SK_LOOKUP(func) \ 469b584ab88SJoe Stringer /* struct bpf_sock_tuple tuple = {} */ \ 470b584ab88SJoe Stringer BPF_MOV64_IMM(BPF_REG_2, 0), \ 471b584ab88SJoe Stringer BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -8), \ 472b584ab88SJoe Stringer BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -16), \ 473b584ab88SJoe Stringer BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -24), \ 474b584ab88SJoe Stringer BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -32), \ 475b584ab88SJoe Stringer BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -40), \ 476b584ab88SJoe Stringer BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -48), \ 477dbaf2877SLorenz Bauer /* sk = func(ctx, &tuple, sizeof tuple, 0, 0) */ \ 478b584ab88SJoe Stringer BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), \ 479b584ab88SJoe Stringer BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48), \ 480b584ab88SJoe Stringer BPF_MOV64_IMM(BPF_REG_3, sizeof(struct bpf_sock_tuple)), \ 481b584ab88SJoe Stringer BPF_MOV64_IMM(BPF_REG_4, 0), \ 482b584ab88SJoe Stringer BPF_MOV64_IMM(BPF_REG_5, 0), \ 483dbaf2877SLorenz Bauer BPF_EMIT_CALL(BPF_FUNC_ ## func) 484b584ab88SJoe Stringer 4856ea848b5SJiong Wang /* BPF_DIRECT_PKT_R2 contains 7 instructions, it initializes default return 4866ea848b5SJiong Wang * value into 0 and does necessary preparation for direct packet access 4876ea848b5SJiong Wang * through r2. The allowed access range is 8 bytes. 4886ea848b5SJiong Wang */ 4896ea848b5SJiong Wang #define BPF_DIRECT_PKT_R2 \ 4906ea848b5SJiong Wang BPF_MOV64_IMM(BPF_REG_0, 0), \ 4916ea848b5SJiong Wang BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \ 4926ea848b5SJiong Wang offsetof(struct __sk_buff, data)), \ 4936ea848b5SJiong Wang BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \ 4946ea848b5SJiong Wang offsetof(struct __sk_buff, data_end)), \ 4956ea848b5SJiong Wang BPF_MOV64_REG(BPF_REG_4, BPF_REG_2), \ 4966ea848b5SJiong Wang BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8), \ 4976ea848b5SJiong Wang BPF_JMP_REG(BPF_JLE, BPF_REG_4, BPF_REG_3, 1), \ 4986ea848b5SJiong Wang BPF_EXIT_INSN() 4996ea848b5SJiong Wang 5006ea848b5SJiong Wang /* BPF_RAND_UEXT_R7 contains 4 instructions, it initializes R7 into a random 5016ea848b5SJiong Wang * positive u32, and zero-extend it into 64-bit. 5026ea848b5SJiong Wang */ 5036ea848b5SJiong Wang #define BPF_RAND_UEXT_R7 \ 5046ea848b5SJiong Wang BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, \ 5056ea848b5SJiong Wang BPF_FUNC_get_prandom_u32), \ 5066ea848b5SJiong Wang BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), \ 5076ea848b5SJiong Wang BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 33), \ 5086ea848b5SJiong Wang BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 33) 5096ea848b5SJiong Wang 5106ea848b5SJiong Wang /* BPF_RAND_SEXT_R7 contains 5 instructions, it initializes R7 into a random 5116ea848b5SJiong Wang * negative u32, and sign-extend it into 64-bit. 5126ea848b5SJiong Wang */ 5136ea848b5SJiong Wang #define BPF_RAND_SEXT_R7 \ 5146ea848b5SJiong Wang BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, \ 5156ea848b5SJiong Wang BPF_FUNC_get_prandom_u32), \ 5166ea848b5SJiong Wang BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), \ 5176ea848b5SJiong Wang BPF_ALU64_IMM(BPF_OR, BPF_REG_7, 0x80000000), \ 5186ea848b5SJiong Wang BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 32), \ 5196ea848b5SJiong Wang BPF_ALU64_IMM(BPF_ARSH, BPF_REG_7, 32) 5206ea848b5SJiong Wang 5215aa5bd14SDaniel Borkmann static struct bpf_test tests[] = { 5222dfb4012SJakub Kicinski #define FILL_ARRAY 5232dfb4012SJakub Kicinski #include <verifier/tests.h> 5242dfb4012SJakub Kicinski #undef FILL_ARRAY 5255aa5bd14SDaniel Borkmann }; 5265aa5bd14SDaniel Borkmann 5275aa5bd14SDaniel Borkmann static int probe_filter_length(const struct bpf_insn *fp) 5285aa5bd14SDaniel Borkmann { 5295aa5bd14SDaniel Borkmann int len; 5305aa5bd14SDaniel Borkmann 5315aa5bd14SDaniel Borkmann for (len = MAX_INSNS - 1; len > 0; --len) 5325aa5bd14SDaniel Borkmann if (fp[len].code != 0 || fp[len].imm != 0) 5335aa5bd14SDaniel Borkmann break; 5345aa5bd14SDaniel Borkmann return len + 1; 5355aa5bd14SDaniel Borkmann } 5365aa5bd14SDaniel Borkmann 5379acea337SStanislav Fomichev static bool skip_unsupported_map(enum bpf_map_type map_type) 5389acea337SStanislav Fomichev { 53932e608f8SAndrii Nakryiko if (!libbpf_probe_bpf_map_type(map_type, NULL)) { 5409acea337SStanislav Fomichev printf("SKIP (unsupported map type %d)\n", map_type); 5419acea337SStanislav Fomichev skips++; 5429acea337SStanislav Fomichev return true; 5439acea337SStanislav Fomichev } 5449acea337SStanislav Fomichev return false; 5459acea337SStanislav Fomichev } 5469acea337SStanislav Fomichev 547fb2abb73SDaniel Borkmann static int __create_map(uint32_t type, uint32_t size_key, 548fb2abb73SDaniel Borkmann uint32_t size_value, uint32_t max_elem, 549fb2abb73SDaniel Borkmann uint32_t extra_flags) 5505aa5bd14SDaniel Borkmann { 5512fe256a4SAndrii Nakryiko LIBBPF_OPTS(bpf_map_create_opts, opts); 5525aa5bd14SDaniel Borkmann int fd; 5535aa5bd14SDaniel Borkmann 5542fe256a4SAndrii Nakryiko opts.map_flags = (type == BPF_MAP_TYPE_HASH ? BPF_F_NO_PREALLOC : 0) | extra_flags; 5552fe256a4SAndrii Nakryiko fd = bpf_map_create(type, NULL, size_key, size_value, max_elem, &opts); 5569acea337SStanislav Fomichev if (fd < 0) { 5579acea337SStanislav Fomichev if (skip_unsupported_map(type)) 5589acea337SStanislav Fomichev return -1; 5595aa5bd14SDaniel Borkmann printf("Failed to create hash map '%s'!\n", strerror(errno)); 5609acea337SStanislav Fomichev } 5615aa5bd14SDaniel Borkmann 5625aa5bd14SDaniel Borkmann return fd; 5635aa5bd14SDaniel Borkmann } 5645aa5bd14SDaniel Borkmann 565fb2abb73SDaniel Borkmann static int create_map(uint32_t type, uint32_t size_key, 566fb2abb73SDaniel Borkmann uint32_t size_value, uint32_t max_elem) 567fb2abb73SDaniel Borkmann { 568fb2abb73SDaniel Borkmann return __create_map(type, size_key, size_value, max_elem, 0); 569fb2abb73SDaniel Borkmann } 570fb2abb73SDaniel Borkmann 57180c9b2faSDaniel Borkmann static void update_map(int fd, int index) 57280c9b2faSDaniel Borkmann { 57380c9b2faSDaniel Borkmann struct test_val value = { 57480c9b2faSDaniel Borkmann .index = (6 + 1) * sizeof(int), 57580c9b2faSDaniel Borkmann .foo[6] = 0xabcdef12, 57680c9b2faSDaniel Borkmann }; 57780c9b2faSDaniel Borkmann 57880c9b2faSDaniel Borkmann assert(!bpf_map_update_elem(fd, &index, &value, 0)); 57980c9b2faSDaniel Borkmann } 58080c9b2faSDaniel Borkmann 5813123d801SDaniel Borkmann static int create_prog_dummy_simple(enum bpf_prog_type prog_type, int ret) 582b33eb735SDaniel Borkmann { 583b33eb735SDaniel Borkmann struct bpf_insn prog[] = { 5843123d801SDaniel Borkmann BPF_MOV64_IMM(BPF_REG_0, ret), 585b33eb735SDaniel Borkmann BPF_EXIT_INSN(), 586b33eb735SDaniel Borkmann }; 587b33eb735SDaniel Borkmann 588d8e86407SAndrii Nakryiko return bpf_prog_load(prog_type, NULL, "GPL", prog, ARRAY_SIZE(prog), NULL); 589b33eb735SDaniel Borkmann } 590b33eb735SDaniel Borkmann 5913123d801SDaniel Borkmann static int create_prog_dummy_loop(enum bpf_prog_type prog_type, int mfd, 5923123d801SDaniel Borkmann int idx, int ret) 593b33eb735SDaniel Borkmann { 594b33eb735SDaniel Borkmann struct bpf_insn prog[] = { 595b33eb735SDaniel Borkmann BPF_MOV64_IMM(BPF_REG_3, idx), 596b33eb735SDaniel Borkmann BPF_LD_MAP_FD(BPF_REG_2, mfd), 597b33eb735SDaniel Borkmann BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 598b33eb735SDaniel Borkmann BPF_FUNC_tail_call), 5993123d801SDaniel Borkmann BPF_MOV64_IMM(BPF_REG_0, ret), 600b33eb735SDaniel Borkmann BPF_EXIT_INSN(), 601b33eb735SDaniel Borkmann }; 602b33eb735SDaniel Borkmann 603d8e86407SAndrii Nakryiko return bpf_prog_load(prog_type, NULL, "GPL", prog, ARRAY_SIZE(prog), NULL); 604b33eb735SDaniel Borkmann } 605b33eb735SDaniel Borkmann 606aca1a80eSStanislav Fomichev static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem, 6073123d801SDaniel Borkmann int p1key, int p2key, int p3key) 6085aa5bd14SDaniel Borkmann { 6093123d801SDaniel Borkmann int mfd, p1fd, p2fd, p3fd; 6105aa5bd14SDaniel Borkmann 6112fe256a4SAndrii Nakryiko mfd = bpf_map_create(BPF_MAP_TYPE_PROG_ARRAY, NULL, sizeof(int), 6122fe256a4SAndrii Nakryiko sizeof(int), max_elem, NULL); 613b33eb735SDaniel Borkmann if (mfd < 0) { 6149acea337SStanislav Fomichev if (skip_unsupported_map(BPF_MAP_TYPE_PROG_ARRAY)) 6159acea337SStanislav Fomichev return -1; 6165aa5bd14SDaniel Borkmann printf("Failed to create prog array '%s'!\n", strerror(errno)); 617b33eb735SDaniel Borkmann return -1; 618b33eb735SDaniel Borkmann } 6195aa5bd14SDaniel Borkmann 6203123d801SDaniel Borkmann p1fd = create_prog_dummy_simple(prog_type, 42); 6213123d801SDaniel Borkmann p2fd = create_prog_dummy_loop(prog_type, mfd, p2key, 41); 6223123d801SDaniel Borkmann p3fd = create_prog_dummy_simple(prog_type, 24); 6233123d801SDaniel Borkmann if (p1fd < 0 || p2fd < 0 || p3fd < 0) 6243123d801SDaniel Borkmann goto err; 625b33eb735SDaniel Borkmann if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0) 6263123d801SDaniel Borkmann goto err; 627b33eb735SDaniel Borkmann if (bpf_map_update_elem(mfd, &p2key, &p2fd, BPF_ANY) < 0) 6283123d801SDaniel Borkmann goto err; 6293123d801SDaniel Borkmann if (bpf_map_update_elem(mfd, &p3key, &p3fd, BPF_ANY) < 0) { 6303123d801SDaniel Borkmann err: 631b33eb735SDaniel Borkmann close(mfd); 6323123d801SDaniel Borkmann mfd = -1; 6333123d801SDaniel Borkmann } 6343123d801SDaniel Borkmann close(p3fd); 6353123d801SDaniel Borkmann close(p2fd); 6363123d801SDaniel Borkmann close(p1fd); 6373123d801SDaniel Borkmann return mfd; 6385aa5bd14SDaniel Borkmann } 6395aa5bd14SDaniel Borkmann 640fb30d4b7SMartin KaFai Lau static int create_map_in_map(void) 641fb30d4b7SMartin KaFai Lau { 6422fe256a4SAndrii Nakryiko LIBBPF_OPTS(bpf_map_create_opts, opts); 643fb30d4b7SMartin KaFai Lau int inner_map_fd, outer_map_fd; 644fb30d4b7SMartin KaFai Lau 6452fe256a4SAndrii Nakryiko inner_map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(int), 6462fe256a4SAndrii Nakryiko sizeof(int), 1, NULL); 647fb30d4b7SMartin KaFai Lau if (inner_map_fd < 0) { 6489acea337SStanislav Fomichev if (skip_unsupported_map(BPF_MAP_TYPE_ARRAY)) 6499acea337SStanislav Fomichev return -1; 650fb30d4b7SMartin KaFai Lau printf("Failed to create array '%s'!\n", strerror(errno)); 651fb30d4b7SMartin KaFai Lau return inner_map_fd; 652fb30d4b7SMartin KaFai Lau } 653fb30d4b7SMartin KaFai Lau 6542fe256a4SAndrii Nakryiko opts.inner_map_fd = inner_map_fd; 6552fe256a4SAndrii Nakryiko outer_map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, NULL, 6562fe256a4SAndrii Nakryiko sizeof(int), sizeof(int), 1, &opts); 6579acea337SStanislav Fomichev if (outer_map_fd < 0) { 6589acea337SStanislav Fomichev if (skip_unsupported_map(BPF_MAP_TYPE_ARRAY_OF_MAPS)) 6599acea337SStanislav Fomichev return -1; 660fb30d4b7SMartin KaFai Lau printf("Failed to create array of maps '%s'!\n", 661fb30d4b7SMartin KaFai Lau strerror(errno)); 6629acea337SStanislav Fomichev } 663fb30d4b7SMartin KaFai Lau 664fb30d4b7SMartin KaFai Lau close(inner_map_fd); 665fb30d4b7SMartin KaFai Lau 666fb30d4b7SMartin KaFai Lau return outer_map_fd; 667fb30d4b7SMartin KaFai Lau } 668fb30d4b7SMartin KaFai Lau 669a3c6054fSRoman Gushchin static int create_cgroup_storage(bool percpu) 670d4c9f573SRoman Gushchin { 671a3c6054fSRoman Gushchin enum bpf_map_type type = percpu ? BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE : 672a3c6054fSRoman Gushchin BPF_MAP_TYPE_CGROUP_STORAGE; 673d4c9f573SRoman Gushchin int fd; 674d4c9f573SRoman Gushchin 6752fe256a4SAndrii Nakryiko fd = bpf_map_create(type, NULL, sizeof(struct bpf_cgroup_storage_key), 6762fe256a4SAndrii Nakryiko TEST_DATA_LEN, 0, NULL); 6779acea337SStanislav Fomichev if (fd < 0) { 6789acea337SStanislav Fomichev if (skip_unsupported_map(type)) 6799acea337SStanislav Fomichev return -1; 680a3c6054fSRoman Gushchin printf("Failed to create cgroup storage '%s'!\n", 681a3c6054fSRoman Gushchin strerror(errno)); 6829acea337SStanislav Fomichev } 683d4c9f573SRoman Gushchin 684d4c9f573SRoman Gushchin return fd; 685d4c9f573SRoman Gushchin } 686d4c9f573SRoman Gushchin 687b4d4556cSAlexei Starovoitov /* struct bpf_spin_lock { 688b4d4556cSAlexei Starovoitov * int val; 689b4d4556cSAlexei Starovoitov * }; 690b4d4556cSAlexei Starovoitov * struct val { 691b4d4556cSAlexei Starovoitov * int cnt; 692b4d4556cSAlexei Starovoitov * struct bpf_spin_lock l; 693b4d4556cSAlexei Starovoitov * }; 694e60e6962SDmitrii Banshchikov * struct bpf_timer { 695e60e6962SDmitrii Banshchikov * __u64 :64; 696e60e6962SDmitrii Banshchikov * __u64 :64; 697e60e6962SDmitrii Banshchikov * } __attribute__((aligned(8))); 698e60e6962SDmitrii Banshchikov * struct timer { 699e60e6962SDmitrii Banshchikov * struct bpf_timer t; 700e60e6962SDmitrii Banshchikov * }; 70105a945deSKumar Kartikeya Dwivedi * struct btf_ptr { 702*03b77e17SAlexei Starovoitov * struct prog_test_ref_kfunc __kptr_untrusted *ptr; 70305a945deSKumar Kartikeya Dwivedi * struct prog_test_ref_kfunc __kptr *ptr; 704*03b77e17SAlexei Starovoitov * struct prog_test_member __kptr *ptr; 70505a945deSKumar Kartikeya Dwivedi * } 706b4d4556cSAlexei Starovoitov */ 70705a945deSKumar Kartikeya Dwivedi static const char btf_str_sec[] = "\0bpf_spin_lock\0val\0cnt\0l\0bpf_timer\0timer\0t" 708*03b77e17SAlexei Starovoitov "\0btf_ptr\0prog_test_ref_kfunc\0ptr\0kptr\0kptr_untrusted" 70905a945deSKumar Kartikeya Dwivedi "\0prog_test_member"; 710b4d4556cSAlexei Starovoitov static __u32 btf_raw_types[] = { 711b4d4556cSAlexei Starovoitov /* int */ 712b4d4556cSAlexei Starovoitov BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 713b4d4556cSAlexei Starovoitov /* struct bpf_spin_lock */ /* [2] */ 714b4d4556cSAlexei Starovoitov BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4), 715b4d4556cSAlexei Starovoitov BTF_MEMBER_ENC(15, 1, 0), /* int val; */ 716b4d4556cSAlexei Starovoitov /* struct val */ /* [3] */ 717b4d4556cSAlexei Starovoitov BTF_TYPE_ENC(15, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 718b4d4556cSAlexei Starovoitov BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */ 719b4d4556cSAlexei Starovoitov BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */ 720e60e6962SDmitrii Banshchikov /* struct bpf_timer */ /* [4] */ 721e60e6962SDmitrii Banshchikov BTF_TYPE_ENC(25, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 0), 16), 722e60e6962SDmitrii Banshchikov /* struct timer */ /* [5] */ 723e60e6962SDmitrii Banshchikov BTF_TYPE_ENC(35, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 16), 724e60e6962SDmitrii Banshchikov BTF_MEMBER_ENC(41, 4, 0), /* struct bpf_timer t; */ 72505a945deSKumar Kartikeya Dwivedi /* struct prog_test_ref_kfunc */ /* [6] */ 72605a945deSKumar Kartikeya Dwivedi BTF_STRUCT_ENC(51, 0, 0), 727*03b77e17SAlexei Starovoitov BTF_STRUCT_ENC(95, 0, 0), /* [7] */ 728*03b77e17SAlexei Starovoitov /* type tag "kptr_untrusted" */ 729*03b77e17SAlexei Starovoitov BTF_TYPE_TAG_ENC(80, 6), /* [8] */ 73005a945deSKumar Kartikeya Dwivedi /* type tag "kptr" */ 731*03b77e17SAlexei Starovoitov BTF_TYPE_TAG_ENC(75, 6), /* [9] */ 732*03b77e17SAlexei Starovoitov BTF_TYPE_TAG_ENC(75, 7), /* [10] */ 73305a945deSKumar Kartikeya Dwivedi BTF_PTR_ENC(8), /* [11] */ 73405a945deSKumar Kartikeya Dwivedi BTF_PTR_ENC(9), /* [12] */ 73505a945deSKumar Kartikeya Dwivedi BTF_PTR_ENC(10), /* [13] */ 73605a945deSKumar Kartikeya Dwivedi /* struct btf_ptr */ /* [14] */ 73705a945deSKumar Kartikeya Dwivedi BTF_STRUCT_ENC(43, 3, 24), 738*03b77e17SAlexei Starovoitov BTF_MEMBER_ENC(71, 11, 0), /* struct prog_test_ref_kfunc __kptr_untrusted *ptr; */ 739*03b77e17SAlexei Starovoitov BTF_MEMBER_ENC(71, 12, 64), /* struct prog_test_ref_kfunc __kptr *ptr; */ 740*03b77e17SAlexei Starovoitov BTF_MEMBER_ENC(71, 13, 128), /* struct prog_test_member __kptr *ptr; */ 741b4d4556cSAlexei Starovoitov }; 742b4d4556cSAlexei Starovoitov 7437a42008cSEduard Zingerman static char bpf_vlog[UINT_MAX >> 8]; 7447a42008cSEduard Zingerman 7457a42008cSEduard Zingerman static int load_btf_spec(__u32 *types, int types_len, 7467a42008cSEduard Zingerman const char *strings, int strings_len) 747b4d4556cSAlexei Starovoitov { 748b4d4556cSAlexei Starovoitov struct btf_header hdr = { 749b4d4556cSAlexei Starovoitov .magic = BTF_MAGIC, 750b4d4556cSAlexei Starovoitov .version = BTF_VERSION, 751b4d4556cSAlexei Starovoitov .hdr_len = sizeof(struct btf_header), 7527a42008cSEduard Zingerman .type_len = types_len, 7537a42008cSEduard Zingerman .str_off = types_len, 7547a42008cSEduard Zingerman .str_len = strings_len, 755b4d4556cSAlexei Starovoitov }; 756b4d4556cSAlexei Starovoitov void *ptr, *raw_btf; 757b4d4556cSAlexei Starovoitov int btf_fd; 7587a42008cSEduard Zingerman LIBBPF_OPTS(bpf_btf_load_opts, opts, 7597a42008cSEduard Zingerman .log_buf = bpf_vlog, 7607a42008cSEduard Zingerman .log_size = sizeof(bpf_vlog), 7617a42008cSEduard Zingerman .log_level = (verbose 7622a72f595SAndrii Nakryiko ? verif_log_level 7637a42008cSEduard Zingerman : DEFAULT_LIBBPF_LOG_LEVEL), 7647a42008cSEduard Zingerman ); 765b4d4556cSAlexei Starovoitov 7667a42008cSEduard Zingerman raw_btf = malloc(sizeof(hdr) + types_len + strings_len); 767b4d4556cSAlexei Starovoitov 7687a42008cSEduard Zingerman ptr = raw_btf; 769b4d4556cSAlexei Starovoitov memcpy(ptr, &hdr, sizeof(hdr)); 770b4d4556cSAlexei Starovoitov ptr += sizeof(hdr); 7717a42008cSEduard Zingerman memcpy(ptr, types, hdr.type_len); 772b4d4556cSAlexei Starovoitov ptr += hdr.type_len; 7737a42008cSEduard Zingerman memcpy(ptr, strings, hdr.str_len); 774b4d4556cSAlexei Starovoitov ptr += hdr.str_len; 775b4d4556cSAlexei Starovoitov 7767a42008cSEduard Zingerman btf_fd = bpf_btf_load(raw_btf, ptr - raw_btf, &opts); 777b4d4556cSAlexei Starovoitov if (btf_fd < 0) 7787a42008cSEduard Zingerman printf("Failed to load BTF spec: '%s'\n", strerror(errno)); 7797a42008cSEduard Zingerman 7807a42008cSEduard Zingerman free(raw_btf); 7817a42008cSEduard Zingerman 7827a42008cSEduard Zingerman return btf_fd < 0 ? -1 : btf_fd; 7837a42008cSEduard Zingerman } 7847a42008cSEduard Zingerman 7857a42008cSEduard Zingerman static int load_btf(void) 7867a42008cSEduard Zingerman { 7877a42008cSEduard Zingerman return load_btf_spec(btf_raw_types, sizeof(btf_raw_types), 7887a42008cSEduard Zingerman btf_str_sec, sizeof(btf_str_sec)); 7897a42008cSEduard Zingerman } 7907a42008cSEduard Zingerman 7917a42008cSEduard Zingerman static int load_btf_for_test(struct bpf_test *test) 7927a42008cSEduard Zingerman { 7937a42008cSEduard Zingerman int types_num = 0; 7947a42008cSEduard Zingerman 7957a42008cSEduard Zingerman while (types_num < MAX_BTF_TYPES && 7967a42008cSEduard Zingerman test->btf_types[types_num] != BTF_END_RAW) 7977a42008cSEduard Zingerman ++types_num; 7987a42008cSEduard Zingerman 7997a42008cSEduard Zingerman int types_len = types_num * sizeof(test->btf_types[0]); 8007a42008cSEduard Zingerman 8017a42008cSEduard Zingerman return load_btf_spec(test->btf_types, types_len, 8027a42008cSEduard Zingerman test->btf_strings, sizeof(test->btf_strings)); 803b4d4556cSAlexei Starovoitov } 804b4d4556cSAlexei Starovoitov 805b4d4556cSAlexei Starovoitov static int create_map_spin_lock(void) 806b4d4556cSAlexei Starovoitov { 8072fe256a4SAndrii Nakryiko LIBBPF_OPTS(bpf_map_create_opts, opts, 808b4d4556cSAlexei Starovoitov .btf_key_type_id = 1, 809b4d4556cSAlexei Starovoitov .btf_value_type_id = 3, 8102fe256a4SAndrii Nakryiko ); 811b4d4556cSAlexei Starovoitov int fd, btf_fd; 812b4d4556cSAlexei Starovoitov 813b4d4556cSAlexei Starovoitov btf_fd = load_btf(); 814b4d4556cSAlexei Starovoitov if (btf_fd < 0) 815b4d4556cSAlexei Starovoitov return -1; 8162fe256a4SAndrii Nakryiko opts.btf_fd = btf_fd; 8172fe256a4SAndrii Nakryiko fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 8, 1, &opts); 818b4d4556cSAlexei Starovoitov if (fd < 0) 819b4d4556cSAlexei Starovoitov printf("Failed to create map with spin_lock\n"); 820b4d4556cSAlexei Starovoitov return fd; 821b4d4556cSAlexei Starovoitov } 822b4d4556cSAlexei Starovoitov 8237a9bb976SMartin KaFai Lau static int create_sk_storage_map(void) 8247a9bb976SMartin KaFai Lau { 8252fe256a4SAndrii Nakryiko LIBBPF_OPTS(bpf_map_create_opts, opts, 8267a9bb976SMartin KaFai Lau .map_flags = BPF_F_NO_PREALLOC, 8277a9bb976SMartin KaFai Lau .btf_key_type_id = 1, 8287a9bb976SMartin KaFai Lau .btf_value_type_id = 3, 8292fe256a4SAndrii Nakryiko ); 8307a9bb976SMartin KaFai Lau int fd, btf_fd; 8317a9bb976SMartin KaFai Lau 8327a9bb976SMartin KaFai Lau btf_fd = load_btf(); 8337a9bb976SMartin KaFai Lau if (btf_fd < 0) 8347a9bb976SMartin KaFai Lau return -1; 8352fe256a4SAndrii Nakryiko opts.btf_fd = btf_fd; 8362fe256a4SAndrii Nakryiko fd = bpf_map_create(BPF_MAP_TYPE_SK_STORAGE, "test_map", 4, 8, 0, &opts); 8372fe256a4SAndrii Nakryiko close(opts.btf_fd); 8387a9bb976SMartin KaFai Lau if (fd < 0) 8397a9bb976SMartin KaFai Lau printf("Failed to create sk_storage_map\n"); 8407a9bb976SMartin KaFai Lau return fd; 8417a9bb976SMartin KaFai Lau } 8427a9bb976SMartin KaFai Lau 843e60e6962SDmitrii Banshchikov static int create_map_timer(void) 844e60e6962SDmitrii Banshchikov { 845f1246882SAndrii Nakryiko LIBBPF_OPTS(bpf_map_create_opts, opts, 846e60e6962SDmitrii Banshchikov .btf_key_type_id = 1, 847e60e6962SDmitrii Banshchikov .btf_value_type_id = 5, 848f1246882SAndrii Nakryiko ); 849e60e6962SDmitrii Banshchikov int fd, btf_fd; 850e60e6962SDmitrii Banshchikov 851e60e6962SDmitrii Banshchikov btf_fd = load_btf(); 852e60e6962SDmitrii Banshchikov if (btf_fd < 0) 853e60e6962SDmitrii Banshchikov return -1; 854f1246882SAndrii Nakryiko 855f1246882SAndrii Nakryiko opts.btf_fd = btf_fd; 856f1246882SAndrii Nakryiko fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 16, 1, &opts); 857e60e6962SDmitrii Banshchikov if (fd < 0) 858e60e6962SDmitrii Banshchikov printf("Failed to create map with timer\n"); 859e60e6962SDmitrii Banshchikov return fd; 860e60e6962SDmitrii Banshchikov } 861e60e6962SDmitrii Banshchikov 86205a945deSKumar Kartikeya Dwivedi static int create_map_kptr(void) 86305a945deSKumar Kartikeya Dwivedi { 86405a945deSKumar Kartikeya Dwivedi LIBBPF_OPTS(bpf_map_create_opts, opts, 86505a945deSKumar Kartikeya Dwivedi .btf_key_type_id = 1, 86605a945deSKumar Kartikeya Dwivedi .btf_value_type_id = 14, 86705a945deSKumar Kartikeya Dwivedi ); 86805a945deSKumar Kartikeya Dwivedi int fd, btf_fd; 86905a945deSKumar Kartikeya Dwivedi 87005a945deSKumar Kartikeya Dwivedi btf_fd = load_btf(); 87105a945deSKumar Kartikeya Dwivedi if (btf_fd < 0) 87205a945deSKumar Kartikeya Dwivedi return -1; 87305a945deSKumar Kartikeya Dwivedi 87405a945deSKumar Kartikeya Dwivedi opts.btf_fd = btf_fd; 87505a945deSKumar Kartikeya Dwivedi fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "test_map", 4, 24, 1, &opts); 87605a945deSKumar Kartikeya Dwivedi if (fd < 0) 87705a945deSKumar Kartikeya Dwivedi printf("Failed to create map with btf_id pointer\n"); 87805a945deSKumar Kartikeya Dwivedi return fd; 87905a945deSKumar Kartikeya Dwivedi } 88005a945deSKumar Kartikeya Dwivedi 881aca1a80eSStanislav Fomichev static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type, 8820c586079SJoe Stringer struct bpf_insn *prog, int *map_fds) 8835aa5bd14SDaniel Borkmann { 884908142e6SPrashant Bhole int *fixup_map_hash_8b = test->fixup_map_hash_8b; 885908142e6SPrashant Bhole int *fixup_map_hash_48b = test->fixup_map_hash_48b; 886908142e6SPrashant Bhole int *fixup_map_hash_16b = test->fixup_map_hash_16b; 887908142e6SPrashant Bhole int *fixup_map_array_48b = test->fixup_map_array_48b; 8887c85c448SPrashant Bhole int *fixup_map_sockmap = test->fixup_map_sockmap; 8897c85c448SPrashant Bhole int *fixup_map_sockhash = test->fixup_map_sockhash; 8907c85c448SPrashant Bhole int *fixup_map_xskmap = test->fixup_map_xskmap; 8917c85c448SPrashant Bhole int *fixup_map_stacktrace = test->fixup_map_stacktrace; 89206be0864SDaniel Borkmann int *fixup_prog1 = test->fixup_prog1; 89306be0864SDaniel Borkmann int *fixup_prog2 = test->fixup_prog2; 894fb30d4b7SMartin KaFai Lau int *fixup_map_in_map = test->fixup_map_in_map; 895d4c9f573SRoman Gushchin int *fixup_cgroup_storage = test->fixup_cgroup_storage; 896a3c6054fSRoman Gushchin int *fixup_percpu_cgroup_storage = test->fixup_percpu_cgroup_storage; 897b4d4556cSAlexei Starovoitov int *fixup_map_spin_lock = test->fixup_map_spin_lock; 898fb2abb73SDaniel Borkmann int *fixup_map_array_ro = test->fixup_map_array_ro; 899fb2abb73SDaniel Borkmann int *fixup_map_array_wo = test->fixup_map_array_wo; 900fb2abb73SDaniel Borkmann int *fixup_map_array_small = test->fixup_map_array_small; 9017a9bb976SMartin KaFai Lau int *fixup_sk_storage_map = test->fixup_sk_storage_map; 90203cd1d1aSAllan Zhang int *fixup_map_event_output = test->fixup_map_event_output; 903c3210222SJakub Sitnicki int *fixup_map_reuseport_array = test->fixup_map_reuseport_array; 9044237e9f4SGilad Reti int *fixup_map_ringbuf = test->fixup_map_ringbuf; 905e60e6962SDmitrii Banshchikov int *fixup_map_timer = test->fixup_map_timer; 90605a945deSKumar Kartikeya Dwivedi int *fixup_map_kptr = test->fixup_map_kptr; 9070201b807SKumar Kartikeya Dwivedi struct kfunc_btf_id_pair *fixup_kfunc_btf_id = test->fixup_kfunc_btf_id; 9085aa5bd14SDaniel Borkmann 9098aa2d4b4SAlexei Starovoitov if (test->fill_helper) { 9108aa2d4b4SAlexei Starovoitov test->fill_insns = calloc(MAX_TEST_INSNS, sizeof(struct bpf_insn)); 91193731ef0SDaniel Borkmann test->fill_helper(test); 9128aa2d4b4SAlexei Starovoitov } 91393731ef0SDaniel Borkmann 9145aa5bd14SDaniel Borkmann /* Allocating HTs with 1 elem is fine here, since we only test 9155aa5bd14SDaniel Borkmann * for verifier and not do a runtime lookup, so the only thing 9165aa5bd14SDaniel Borkmann * that really matters is value size in this case. 9175aa5bd14SDaniel Borkmann */ 918908142e6SPrashant Bhole if (*fixup_map_hash_8b) { 91906be0864SDaniel Borkmann map_fds[0] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long), 92006be0864SDaniel Borkmann sizeof(long long), 1); 9215aa5bd14SDaniel Borkmann do { 922908142e6SPrashant Bhole prog[*fixup_map_hash_8b].imm = map_fds[0]; 923908142e6SPrashant Bhole fixup_map_hash_8b++; 924908142e6SPrashant Bhole } while (*fixup_map_hash_8b); 9255aa5bd14SDaniel Borkmann } 9265aa5bd14SDaniel Borkmann 927908142e6SPrashant Bhole if (*fixup_map_hash_48b) { 92806be0864SDaniel Borkmann map_fds[1] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long), 92906be0864SDaniel Borkmann sizeof(struct test_val), 1); 9305aa5bd14SDaniel Borkmann do { 931908142e6SPrashant Bhole prog[*fixup_map_hash_48b].imm = map_fds[1]; 932908142e6SPrashant Bhole fixup_map_hash_48b++; 933908142e6SPrashant Bhole } while (*fixup_map_hash_48b); 9345aa5bd14SDaniel Borkmann } 9355aa5bd14SDaniel Borkmann 936908142e6SPrashant Bhole if (*fixup_map_hash_16b) { 93706be0864SDaniel Borkmann map_fds[2] = create_map(BPF_MAP_TYPE_HASH, sizeof(long long), 93806be0864SDaniel Borkmann sizeof(struct other_val), 1); 9395f90dd6aSPaul Chaignon do { 940908142e6SPrashant Bhole prog[*fixup_map_hash_16b].imm = map_fds[2]; 941908142e6SPrashant Bhole fixup_map_hash_16b++; 942908142e6SPrashant Bhole } while (*fixup_map_hash_16b); 9435f90dd6aSPaul Chaignon } 9445f90dd6aSPaul Chaignon 945908142e6SPrashant Bhole if (*fixup_map_array_48b) { 94606be0864SDaniel Borkmann map_fds[3] = create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 94706be0864SDaniel Borkmann sizeof(struct test_val), 1); 94880c9b2faSDaniel Borkmann update_map(map_fds[3], 0); 9495aa5bd14SDaniel Borkmann do { 950908142e6SPrashant Bhole prog[*fixup_map_array_48b].imm = map_fds[3]; 951908142e6SPrashant Bhole fixup_map_array_48b++; 952908142e6SPrashant Bhole } while (*fixup_map_array_48b); 95306be0864SDaniel Borkmann } 95406be0864SDaniel Borkmann 95506be0864SDaniel Borkmann if (*fixup_prog1) { 9563123d801SDaniel Borkmann map_fds[4] = create_prog_array(prog_type, 4, 0, 1, 2); 95706be0864SDaniel Borkmann do { 95806be0864SDaniel Borkmann prog[*fixup_prog1].imm = map_fds[4]; 95906be0864SDaniel Borkmann fixup_prog1++; 96006be0864SDaniel Borkmann } while (*fixup_prog1); 96106be0864SDaniel Borkmann } 96206be0864SDaniel Borkmann 96306be0864SDaniel Borkmann if (*fixup_prog2) { 9643123d801SDaniel Borkmann map_fds[5] = create_prog_array(prog_type, 8, 7, 1, 2); 96506be0864SDaniel Borkmann do { 96606be0864SDaniel Borkmann prog[*fixup_prog2].imm = map_fds[5]; 96706be0864SDaniel Borkmann fixup_prog2++; 96806be0864SDaniel Borkmann } while (*fixup_prog2); 9695aa5bd14SDaniel Borkmann } 970fb30d4b7SMartin KaFai Lau 971fb30d4b7SMartin KaFai Lau if (*fixup_map_in_map) { 97206be0864SDaniel Borkmann map_fds[6] = create_map_in_map(); 973fb30d4b7SMartin KaFai Lau do { 97406be0864SDaniel Borkmann prog[*fixup_map_in_map].imm = map_fds[6]; 975fb30d4b7SMartin KaFai Lau fixup_map_in_map++; 976fb30d4b7SMartin KaFai Lau } while (*fixup_map_in_map); 977fb30d4b7SMartin KaFai Lau } 978d4c9f573SRoman Gushchin 979d4c9f573SRoman Gushchin if (*fixup_cgroup_storage) { 980a3c6054fSRoman Gushchin map_fds[7] = create_cgroup_storage(false); 981d4c9f573SRoman Gushchin do { 982d4c9f573SRoman Gushchin prog[*fixup_cgroup_storage].imm = map_fds[7]; 983d4c9f573SRoman Gushchin fixup_cgroup_storage++; 984d4c9f573SRoman Gushchin } while (*fixup_cgroup_storage); 985d4c9f573SRoman Gushchin } 986a3c6054fSRoman Gushchin 987a3c6054fSRoman Gushchin if (*fixup_percpu_cgroup_storage) { 988a3c6054fSRoman Gushchin map_fds[8] = create_cgroup_storage(true); 989a3c6054fSRoman Gushchin do { 990a3c6054fSRoman Gushchin prog[*fixup_percpu_cgroup_storage].imm = map_fds[8]; 991a3c6054fSRoman Gushchin fixup_percpu_cgroup_storage++; 992a3c6054fSRoman Gushchin } while (*fixup_percpu_cgroup_storage); 993a3c6054fSRoman Gushchin } 9947c85c448SPrashant Bhole if (*fixup_map_sockmap) { 9957c85c448SPrashant Bhole map_fds[9] = create_map(BPF_MAP_TYPE_SOCKMAP, sizeof(int), 9967c85c448SPrashant Bhole sizeof(int), 1); 9977c85c448SPrashant Bhole do { 9987c85c448SPrashant Bhole prog[*fixup_map_sockmap].imm = map_fds[9]; 9997c85c448SPrashant Bhole fixup_map_sockmap++; 10007c85c448SPrashant Bhole } while (*fixup_map_sockmap); 10017c85c448SPrashant Bhole } 10027c85c448SPrashant Bhole if (*fixup_map_sockhash) { 10037c85c448SPrashant Bhole map_fds[10] = create_map(BPF_MAP_TYPE_SOCKHASH, sizeof(int), 10047c85c448SPrashant Bhole sizeof(int), 1); 10057c85c448SPrashant Bhole do { 10067c85c448SPrashant Bhole prog[*fixup_map_sockhash].imm = map_fds[10]; 10077c85c448SPrashant Bhole fixup_map_sockhash++; 10087c85c448SPrashant Bhole } while (*fixup_map_sockhash); 10097c85c448SPrashant Bhole } 10107c85c448SPrashant Bhole if (*fixup_map_xskmap) { 10117c85c448SPrashant Bhole map_fds[11] = create_map(BPF_MAP_TYPE_XSKMAP, sizeof(int), 10127c85c448SPrashant Bhole sizeof(int), 1); 10137c85c448SPrashant Bhole do { 10147c85c448SPrashant Bhole prog[*fixup_map_xskmap].imm = map_fds[11]; 10157c85c448SPrashant Bhole fixup_map_xskmap++; 10167c85c448SPrashant Bhole } while (*fixup_map_xskmap); 10177c85c448SPrashant Bhole } 10187c85c448SPrashant Bhole if (*fixup_map_stacktrace) { 10197c85c448SPrashant Bhole map_fds[12] = create_map(BPF_MAP_TYPE_STACK_TRACE, sizeof(u32), 10207c85c448SPrashant Bhole sizeof(u64), 1); 10217c85c448SPrashant Bhole do { 10227c85c448SPrashant Bhole prog[*fixup_map_stacktrace].imm = map_fds[12]; 10237c85c448SPrashant Bhole fixup_map_stacktrace++; 1024c2a20a27SStanislav Fomichev } while (*fixup_map_stacktrace); 10257c85c448SPrashant Bhole } 1026b4d4556cSAlexei Starovoitov if (*fixup_map_spin_lock) { 1027b4d4556cSAlexei Starovoitov map_fds[13] = create_map_spin_lock(); 1028b4d4556cSAlexei Starovoitov do { 1029b4d4556cSAlexei Starovoitov prog[*fixup_map_spin_lock].imm = map_fds[13]; 1030b4d4556cSAlexei Starovoitov fixup_map_spin_lock++; 1031b4d4556cSAlexei Starovoitov } while (*fixup_map_spin_lock); 1032b4d4556cSAlexei Starovoitov } 1033fb2abb73SDaniel Borkmann if (*fixup_map_array_ro) { 1034fb2abb73SDaniel Borkmann map_fds[14] = __create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 1035fb2abb73SDaniel Borkmann sizeof(struct test_val), 1, 1036fb2abb73SDaniel Borkmann BPF_F_RDONLY_PROG); 1037fb2abb73SDaniel Borkmann update_map(map_fds[14], 0); 1038fb2abb73SDaniel Borkmann do { 1039fb2abb73SDaniel Borkmann prog[*fixup_map_array_ro].imm = map_fds[14]; 1040fb2abb73SDaniel Borkmann fixup_map_array_ro++; 1041fb2abb73SDaniel Borkmann } while (*fixup_map_array_ro); 1042fb2abb73SDaniel Borkmann } 1043fb2abb73SDaniel Borkmann if (*fixup_map_array_wo) { 1044fb2abb73SDaniel Borkmann map_fds[15] = __create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 1045fb2abb73SDaniel Borkmann sizeof(struct test_val), 1, 1046fb2abb73SDaniel Borkmann BPF_F_WRONLY_PROG); 1047fb2abb73SDaniel Borkmann update_map(map_fds[15], 0); 1048fb2abb73SDaniel Borkmann do { 1049fb2abb73SDaniel Borkmann prog[*fixup_map_array_wo].imm = map_fds[15]; 1050fb2abb73SDaniel Borkmann fixup_map_array_wo++; 1051fb2abb73SDaniel Borkmann } while (*fixup_map_array_wo); 1052fb2abb73SDaniel Borkmann } 1053fb2abb73SDaniel Borkmann if (*fixup_map_array_small) { 1054fb2abb73SDaniel Borkmann map_fds[16] = __create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), 1055fb2abb73SDaniel Borkmann 1, 1, 0); 1056fb2abb73SDaniel Borkmann update_map(map_fds[16], 0); 1057fb2abb73SDaniel Borkmann do { 1058fb2abb73SDaniel Borkmann prog[*fixup_map_array_small].imm = map_fds[16]; 1059fb2abb73SDaniel Borkmann fixup_map_array_small++; 1060fb2abb73SDaniel Borkmann } while (*fixup_map_array_small); 1061fb2abb73SDaniel Borkmann } 10627a9bb976SMartin KaFai Lau if (*fixup_sk_storage_map) { 10637a9bb976SMartin KaFai Lau map_fds[17] = create_sk_storage_map(); 10647a9bb976SMartin KaFai Lau do { 10657a9bb976SMartin KaFai Lau prog[*fixup_sk_storage_map].imm = map_fds[17]; 10667a9bb976SMartin KaFai Lau fixup_sk_storage_map++; 10677a9bb976SMartin KaFai Lau } while (*fixup_sk_storage_map); 10687a9bb976SMartin KaFai Lau } 106903cd1d1aSAllan Zhang if (*fixup_map_event_output) { 107003cd1d1aSAllan Zhang map_fds[18] = __create_map(BPF_MAP_TYPE_PERF_EVENT_ARRAY, 107103cd1d1aSAllan Zhang sizeof(int), sizeof(int), 1, 0); 107203cd1d1aSAllan Zhang do { 107303cd1d1aSAllan Zhang prog[*fixup_map_event_output].imm = map_fds[18]; 107403cd1d1aSAllan Zhang fixup_map_event_output++; 107503cd1d1aSAllan Zhang } while (*fixup_map_event_output); 107603cd1d1aSAllan Zhang } 1077c3210222SJakub Sitnicki if (*fixup_map_reuseport_array) { 1078c3210222SJakub Sitnicki map_fds[19] = __create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 1079c3210222SJakub Sitnicki sizeof(u32), sizeof(u64), 1, 0); 1080c3210222SJakub Sitnicki do { 1081c3210222SJakub Sitnicki prog[*fixup_map_reuseport_array].imm = map_fds[19]; 1082c3210222SJakub Sitnicki fixup_map_reuseport_array++; 1083c3210222SJakub Sitnicki } while (*fixup_map_reuseport_array); 1084c3210222SJakub Sitnicki } 10854237e9f4SGilad Reti if (*fixup_map_ringbuf) { 10864237e9f4SGilad Reti map_fds[20] = create_map(BPF_MAP_TYPE_RINGBUF, 0, 10874237e9f4SGilad Reti 0, 4096); 10884237e9f4SGilad Reti do { 10894237e9f4SGilad Reti prog[*fixup_map_ringbuf].imm = map_fds[20]; 10904237e9f4SGilad Reti fixup_map_ringbuf++; 10914237e9f4SGilad Reti } while (*fixup_map_ringbuf); 10924237e9f4SGilad Reti } 1093e60e6962SDmitrii Banshchikov if (*fixup_map_timer) { 1094e60e6962SDmitrii Banshchikov map_fds[21] = create_map_timer(); 1095e60e6962SDmitrii Banshchikov do { 1096e60e6962SDmitrii Banshchikov prog[*fixup_map_timer].imm = map_fds[21]; 1097e60e6962SDmitrii Banshchikov fixup_map_timer++; 1098e60e6962SDmitrii Banshchikov } while (*fixup_map_timer); 1099e60e6962SDmitrii Banshchikov } 110005a945deSKumar Kartikeya Dwivedi if (*fixup_map_kptr) { 110105a945deSKumar Kartikeya Dwivedi map_fds[22] = create_map_kptr(); 110205a945deSKumar Kartikeya Dwivedi do { 110305a945deSKumar Kartikeya Dwivedi prog[*fixup_map_kptr].imm = map_fds[22]; 110405a945deSKumar Kartikeya Dwivedi fixup_map_kptr++; 110505a945deSKumar Kartikeya Dwivedi } while (*fixup_map_kptr); 110605a945deSKumar Kartikeya Dwivedi } 11070201b807SKumar Kartikeya Dwivedi 11080201b807SKumar Kartikeya Dwivedi /* Patch in kfunc BTF IDs */ 11090201b807SKumar Kartikeya Dwivedi if (fixup_kfunc_btf_id->kfunc) { 11100201b807SKumar Kartikeya Dwivedi struct btf *btf; 11110201b807SKumar Kartikeya Dwivedi int btf_id; 11120201b807SKumar Kartikeya Dwivedi 11130201b807SKumar Kartikeya Dwivedi do { 11140201b807SKumar Kartikeya Dwivedi btf_id = 0; 11150201b807SKumar Kartikeya Dwivedi btf = btf__load_vmlinux_btf(); 11160201b807SKumar Kartikeya Dwivedi if (btf) { 11170201b807SKumar Kartikeya Dwivedi btf_id = btf__find_by_name_kind(btf, 11180201b807SKumar Kartikeya Dwivedi fixup_kfunc_btf_id->kfunc, 11190201b807SKumar Kartikeya Dwivedi BTF_KIND_FUNC); 11200201b807SKumar Kartikeya Dwivedi btf_id = btf_id < 0 ? 0 : btf_id; 11210201b807SKumar Kartikeya Dwivedi } 11220201b807SKumar Kartikeya Dwivedi btf__free(btf); 11230201b807SKumar Kartikeya Dwivedi prog[fixup_kfunc_btf_id->insn_idx].imm = btf_id; 11240201b807SKumar Kartikeya Dwivedi fixup_kfunc_btf_id++; 11250201b807SKumar Kartikeya Dwivedi } while (fixup_kfunc_btf_id->kfunc); 11260201b807SKumar Kartikeya Dwivedi } 11275aa5bd14SDaniel Borkmann } 11285aa5bd14SDaniel Borkmann 112981626001SAlexei Starovoitov struct libcap { 113081626001SAlexei Starovoitov struct __user_cap_header_struct hdr; 113181626001SAlexei Starovoitov struct __user_cap_data_struct data[2]; 113281626001SAlexei Starovoitov }; 113381626001SAlexei Starovoitov 1134832c6f2cSDaniel Borkmann static int set_admin(bool admin) 1135832c6f2cSDaniel Borkmann { 1136b1c2768aSMartin KaFai Lau int err; 1137832c6f2cSDaniel Borkmann 113881626001SAlexei Starovoitov if (admin) { 1139b1c2768aSMartin KaFai Lau err = cap_enable_effective(ADMIN_CAPS, NULL); 1140b1c2768aSMartin KaFai Lau if (err) 1141b1c2768aSMartin KaFai Lau perror("cap_enable_effective(ADMIN_CAPS)"); 114281626001SAlexei Starovoitov } else { 1143b1c2768aSMartin KaFai Lau err = cap_disable_effective(ADMIN_CAPS, NULL); 1144b1c2768aSMartin KaFai Lau if (err) 1145b1c2768aSMartin KaFai Lau perror("cap_disable_effective(ADMIN_CAPS)"); 114681626001SAlexei Starovoitov } 1147b1c2768aSMartin KaFai Lau 1148b1c2768aSMartin KaFai Lau return err; 1149832c6f2cSDaniel Borkmann } 1150832c6f2cSDaniel Borkmann 11515a8d5209SJakub Kicinski static int do_prog_test_run(int fd_prog, bool unpriv, uint32_t expected_val, 11525a8d5209SJakub Kicinski void *data, size_t size_data) 11535a8d5209SJakub Kicinski { 11545a8d5209SJakub Kicinski __u8 tmp[TEST_DATA_LEN << 2]; 11555a8d5209SJakub Kicinski __u32 size_tmp = sizeof(tmp); 11565f61b7c6SFlorian Lehner int err, saved_errno; 115704fcb5f9SDelyan Kratunov LIBBPF_OPTS(bpf_test_run_opts, topts, 115804fcb5f9SDelyan Kratunov .data_in = data, 115904fcb5f9SDelyan Kratunov .data_size_in = size_data, 116004fcb5f9SDelyan Kratunov .data_out = tmp, 116104fcb5f9SDelyan Kratunov .data_size_out = size_tmp, 116204fcb5f9SDelyan Kratunov .repeat = 1, 116304fcb5f9SDelyan Kratunov ); 11645a8d5209SJakub Kicinski 11655a8d5209SJakub Kicinski if (unpriv) 11665a8d5209SJakub Kicinski set_admin(true); 116704fcb5f9SDelyan Kratunov err = bpf_prog_test_run_opts(fd_prog, &topts); 11685f61b7c6SFlorian Lehner saved_errno = errno; 11695f61b7c6SFlorian Lehner 11705a8d5209SJakub Kicinski if (unpriv) 11715a8d5209SJakub Kicinski set_admin(false); 11725f61b7c6SFlorian Lehner 11735f61b7c6SFlorian Lehner if (err) { 11745f61b7c6SFlorian Lehner switch (saved_errno) { 11755319255bSIlya Leoshkevich case ENOTSUPP: 11765f61b7c6SFlorian Lehner printf("Did not run the program (not supported) "); 11775f61b7c6SFlorian Lehner return 0; 11785f61b7c6SFlorian Lehner case EPERM: 11795f61b7c6SFlorian Lehner if (unpriv) { 11805f61b7c6SFlorian Lehner printf("Did not run the program (no permission) "); 11815f61b7c6SFlorian Lehner return 0; 11825f61b7c6SFlorian Lehner } 11835f61b7c6SFlorian Lehner /* fallthrough; */ 11845f61b7c6SFlorian Lehner default: 11855f61b7c6SFlorian Lehner printf("FAIL: Unexpected bpf_prog_test_run error (%s) ", 11865f61b7c6SFlorian Lehner strerror(saved_errno)); 11875a8d5209SJakub Kicinski return err; 11885a8d5209SJakub Kicinski } 11895f61b7c6SFlorian Lehner } 11905f61b7c6SFlorian Lehner 119104fcb5f9SDelyan Kratunov if (topts.retval != expected_val && expected_val != POINTER_VALUE) { 119204fcb5f9SDelyan Kratunov printf("FAIL retval %d != %d ", topts.retval, expected_val); 11935a8d5209SJakub Kicinski return 1; 11945a8d5209SJakub Kicinski } 11955a8d5209SJakub Kicinski 11965a8d5209SJakub Kicinski return 0; 11975a8d5209SJakub Kicinski } 11985a8d5209SJakub Kicinski 1199060fd103SAndrei Matei /* Returns true if every part of exp (tab-separated) appears in log, in order. 1200060fd103SAndrei Matei * 1201060fd103SAndrei Matei * If exp is an empty string, returns true. 1202060fd103SAndrei Matei */ 1203e8c13c4dSAlexei Starovoitov static bool cmp_str_seq(const char *log, const char *exp) 1204e8c13c4dSAlexei Starovoitov { 1205060fd103SAndrei Matei char needle[200]; 1206e8c13c4dSAlexei Starovoitov const char *p, *q; 1207e8c13c4dSAlexei Starovoitov int len; 1208e8c13c4dSAlexei Starovoitov 1209e8c13c4dSAlexei Starovoitov do { 1210060fd103SAndrei Matei if (!strlen(exp)) 1211060fd103SAndrei Matei break; 1212e8c13c4dSAlexei Starovoitov p = strchr(exp, '\t'); 1213e8c13c4dSAlexei Starovoitov if (!p) 1214e8c13c4dSAlexei Starovoitov p = exp + strlen(exp); 1215e8c13c4dSAlexei Starovoitov 1216e8c13c4dSAlexei Starovoitov len = p - exp; 1217e8c13c4dSAlexei Starovoitov if (len >= sizeof(needle) || !len) { 1218e8c13c4dSAlexei Starovoitov printf("FAIL\nTestcase bug\n"); 1219e8c13c4dSAlexei Starovoitov return false; 1220e8c13c4dSAlexei Starovoitov } 1221e8c13c4dSAlexei Starovoitov strncpy(needle, exp, len); 1222e8c13c4dSAlexei Starovoitov needle[len] = 0; 1223e8c13c4dSAlexei Starovoitov q = strstr(log, needle); 1224e8c13c4dSAlexei Starovoitov if (!q) { 1225060fd103SAndrei Matei printf("FAIL\nUnexpected verifier log!\n" 1226e8c13c4dSAlexei Starovoitov "EXP: %s\nRES:\n", needle); 1227e8c13c4dSAlexei Starovoitov return false; 1228e8c13c4dSAlexei Starovoitov } 1229e8c13c4dSAlexei Starovoitov log = q + len; 1230e8c13c4dSAlexei Starovoitov exp = p + 1; 1231e8c13c4dSAlexei Starovoitov } while (*p); 1232e8c13c4dSAlexei Starovoitov return true; 1233e8c13c4dSAlexei Starovoitov } 1234e8c13c4dSAlexei Starovoitov 1235933ff531SEduard Zingerman static int get_xlated_program(int fd_prog, struct bpf_insn **buf, int *cnt) 1236933ff531SEduard Zingerman { 1237933ff531SEduard Zingerman struct bpf_prog_info info = {}; 1238933ff531SEduard Zingerman __u32 info_len = sizeof(info); 1239933ff531SEduard Zingerman __u32 xlated_prog_len; 1240933ff531SEduard Zingerman __u32 buf_element_size = sizeof(struct bpf_insn); 1241933ff531SEduard Zingerman 1242c5a237a4SIlya Leoshkevich if (bpf_prog_get_info_by_fd(fd_prog, &info, &info_len)) { 1243c5a237a4SIlya Leoshkevich perror("bpf_prog_get_info_by_fd failed"); 1244933ff531SEduard Zingerman return -1; 1245933ff531SEduard Zingerman } 1246933ff531SEduard Zingerman 1247933ff531SEduard Zingerman xlated_prog_len = info.xlated_prog_len; 1248933ff531SEduard Zingerman if (xlated_prog_len % buf_element_size) { 1249933ff531SEduard Zingerman printf("Program length %d is not multiple of %d\n", 1250933ff531SEduard Zingerman xlated_prog_len, buf_element_size); 1251933ff531SEduard Zingerman return -1; 1252933ff531SEduard Zingerman } 1253933ff531SEduard Zingerman 1254933ff531SEduard Zingerman *cnt = xlated_prog_len / buf_element_size; 1255933ff531SEduard Zingerman *buf = calloc(*cnt, buf_element_size); 1256933ff531SEduard Zingerman if (!buf) { 1257933ff531SEduard Zingerman perror("can't allocate xlated program buffer"); 1258933ff531SEduard Zingerman return -ENOMEM; 1259933ff531SEduard Zingerman } 1260933ff531SEduard Zingerman 1261933ff531SEduard Zingerman bzero(&info, sizeof(info)); 1262933ff531SEduard Zingerman info.xlated_prog_len = xlated_prog_len; 12630811664dSPu Lehui info.xlated_prog_insns = (__u64)(unsigned long)*buf; 1264c5a237a4SIlya Leoshkevich if (bpf_prog_get_info_by_fd(fd_prog, &info, &info_len)) { 1265c5a237a4SIlya Leoshkevich perror("second bpf_prog_get_info_by_fd failed"); 1266933ff531SEduard Zingerman goto out_free_buf; 1267933ff531SEduard Zingerman } 1268933ff531SEduard Zingerman 1269933ff531SEduard Zingerman return 0; 1270933ff531SEduard Zingerman 1271933ff531SEduard Zingerman out_free_buf: 1272933ff531SEduard Zingerman free(*buf); 1273933ff531SEduard Zingerman return -1; 1274933ff531SEduard Zingerman } 1275933ff531SEduard Zingerman 1276933ff531SEduard Zingerman static bool is_null_insn(struct bpf_insn *insn) 1277933ff531SEduard Zingerman { 1278933ff531SEduard Zingerman struct bpf_insn null_insn = {}; 1279933ff531SEduard Zingerman 1280933ff531SEduard Zingerman return memcmp(insn, &null_insn, sizeof(null_insn)) == 0; 1281933ff531SEduard Zingerman } 1282933ff531SEduard Zingerman 1283933ff531SEduard Zingerman static bool is_skip_insn(struct bpf_insn *insn) 1284933ff531SEduard Zingerman { 1285933ff531SEduard Zingerman struct bpf_insn skip_insn = SKIP_INSNS(); 1286933ff531SEduard Zingerman 1287933ff531SEduard Zingerman return memcmp(insn, &skip_insn, sizeof(skip_insn)) == 0; 1288933ff531SEduard Zingerman } 1289933ff531SEduard Zingerman 1290933ff531SEduard Zingerman static int null_terminated_insn_len(struct bpf_insn *seq, int max_len) 1291933ff531SEduard Zingerman { 1292933ff531SEduard Zingerman int i; 1293933ff531SEduard Zingerman 1294933ff531SEduard Zingerman for (i = 0; i < max_len; ++i) { 1295933ff531SEduard Zingerman if (is_null_insn(&seq[i])) 1296933ff531SEduard Zingerman return i; 1297933ff531SEduard Zingerman } 1298933ff531SEduard Zingerman return max_len; 1299933ff531SEduard Zingerman } 1300933ff531SEduard Zingerman 1301933ff531SEduard Zingerman static bool compare_masked_insn(struct bpf_insn *orig, struct bpf_insn *masked) 1302933ff531SEduard Zingerman { 1303933ff531SEduard Zingerman struct bpf_insn orig_masked; 1304933ff531SEduard Zingerman 1305933ff531SEduard Zingerman memcpy(&orig_masked, orig, sizeof(orig_masked)); 1306933ff531SEduard Zingerman if (masked->imm == INSN_IMM_MASK) 1307933ff531SEduard Zingerman orig_masked.imm = INSN_IMM_MASK; 1308933ff531SEduard Zingerman if (masked->off == INSN_OFF_MASK) 1309933ff531SEduard Zingerman orig_masked.off = INSN_OFF_MASK; 1310933ff531SEduard Zingerman 1311933ff531SEduard Zingerman return memcmp(&orig_masked, masked, sizeof(orig_masked)) == 0; 1312933ff531SEduard Zingerman } 1313933ff531SEduard Zingerman 1314933ff531SEduard Zingerman static int find_insn_subseq(struct bpf_insn *seq, struct bpf_insn *subseq, 1315933ff531SEduard Zingerman int seq_len, int subseq_len) 1316933ff531SEduard Zingerman { 1317933ff531SEduard Zingerman int i, j; 1318933ff531SEduard Zingerman 1319933ff531SEduard Zingerman if (subseq_len > seq_len) 1320933ff531SEduard Zingerman return -1; 1321933ff531SEduard Zingerman 1322933ff531SEduard Zingerman for (i = 0; i < seq_len - subseq_len + 1; ++i) { 1323933ff531SEduard Zingerman bool found = true; 1324933ff531SEduard Zingerman 1325933ff531SEduard Zingerman for (j = 0; j < subseq_len; ++j) { 1326933ff531SEduard Zingerman if (!compare_masked_insn(&seq[i + j], &subseq[j])) { 1327933ff531SEduard Zingerman found = false; 1328933ff531SEduard Zingerman break; 1329933ff531SEduard Zingerman } 1330933ff531SEduard Zingerman } 1331933ff531SEduard Zingerman if (found) 1332933ff531SEduard Zingerman return i; 1333933ff531SEduard Zingerman } 1334933ff531SEduard Zingerman 1335933ff531SEduard Zingerman return -1; 1336933ff531SEduard Zingerman } 1337933ff531SEduard Zingerman 1338933ff531SEduard Zingerman static int find_skip_insn_marker(struct bpf_insn *seq, int len) 1339933ff531SEduard Zingerman { 1340933ff531SEduard Zingerman int i; 1341933ff531SEduard Zingerman 1342933ff531SEduard Zingerman for (i = 0; i < len; ++i) 1343933ff531SEduard Zingerman if (is_skip_insn(&seq[i])) 1344933ff531SEduard Zingerman return i; 1345933ff531SEduard Zingerman 1346933ff531SEduard Zingerman return -1; 1347933ff531SEduard Zingerman } 1348933ff531SEduard Zingerman 1349933ff531SEduard Zingerman /* Return true if all sub-sequences in `subseqs` could be found in 1350933ff531SEduard Zingerman * `seq` one after another. Sub-sequences are separated by a single 1351933ff531SEduard Zingerman * nil instruction. 1352933ff531SEduard Zingerman */ 1353933ff531SEduard Zingerman static bool find_all_insn_subseqs(struct bpf_insn *seq, struct bpf_insn *subseqs, 1354933ff531SEduard Zingerman int seq_len, int max_subseqs_len) 1355933ff531SEduard Zingerman { 1356933ff531SEduard Zingerman int subseqs_len = null_terminated_insn_len(subseqs, max_subseqs_len); 1357933ff531SEduard Zingerman 1358933ff531SEduard Zingerman while (subseqs_len > 0) { 1359933ff531SEduard Zingerman int skip_idx = find_skip_insn_marker(subseqs, subseqs_len); 1360933ff531SEduard Zingerman int cur_subseq_len = skip_idx < 0 ? subseqs_len : skip_idx; 1361933ff531SEduard Zingerman int subseq_idx = find_insn_subseq(seq, subseqs, 1362933ff531SEduard Zingerman seq_len, cur_subseq_len); 1363933ff531SEduard Zingerman 1364933ff531SEduard Zingerman if (subseq_idx < 0) 1365933ff531SEduard Zingerman return false; 1366933ff531SEduard Zingerman seq += subseq_idx + cur_subseq_len; 1367933ff531SEduard Zingerman seq_len -= subseq_idx + cur_subseq_len; 1368933ff531SEduard Zingerman subseqs += cur_subseq_len + 1; 1369933ff531SEduard Zingerman subseqs_len -= cur_subseq_len + 1; 1370933ff531SEduard Zingerman } 1371933ff531SEduard Zingerman 1372933ff531SEduard Zingerman return true; 1373933ff531SEduard Zingerman } 1374933ff531SEduard Zingerman 1375933ff531SEduard Zingerman static void print_insn(struct bpf_insn *buf, int cnt) 1376933ff531SEduard Zingerman { 1377933ff531SEduard Zingerman int i; 1378933ff531SEduard Zingerman 1379933ff531SEduard Zingerman printf(" addr op d s off imm\n"); 1380933ff531SEduard Zingerman for (i = 0; i < cnt; ++i) { 1381933ff531SEduard Zingerman struct bpf_insn *insn = &buf[i]; 1382933ff531SEduard Zingerman 1383933ff531SEduard Zingerman if (is_null_insn(insn)) 1384933ff531SEduard Zingerman break; 1385933ff531SEduard Zingerman 1386933ff531SEduard Zingerman if (is_skip_insn(insn)) 1387933ff531SEduard Zingerman printf(" ...\n"); 1388933ff531SEduard Zingerman else 1389933ff531SEduard Zingerman printf(" %04x: %02x %1x %x %04hx %08x\n", 1390933ff531SEduard Zingerman i, insn->code, insn->dst_reg, 1391933ff531SEduard Zingerman insn->src_reg, insn->off, insn->imm); 1392933ff531SEduard Zingerman } 1393933ff531SEduard Zingerman } 1394933ff531SEduard Zingerman 1395933ff531SEduard Zingerman static bool check_xlated_program(struct bpf_test *test, int fd_prog) 1396933ff531SEduard Zingerman { 1397933ff531SEduard Zingerman struct bpf_insn *buf; 1398933ff531SEduard Zingerman int cnt; 1399933ff531SEduard Zingerman bool result = true; 1400933ff531SEduard Zingerman bool check_expected = !is_null_insn(test->expected_insns); 1401933ff531SEduard Zingerman bool check_unexpected = !is_null_insn(test->unexpected_insns); 1402933ff531SEduard Zingerman 1403933ff531SEduard Zingerman if (!check_expected && !check_unexpected) 1404933ff531SEduard Zingerman goto out; 1405933ff531SEduard Zingerman 1406933ff531SEduard Zingerman if (get_xlated_program(fd_prog, &buf, &cnt)) { 1407933ff531SEduard Zingerman printf("FAIL: can't get xlated program\n"); 1408933ff531SEduard Zingerman result = false; 1409933ff531SEduard Zingerman goto out; 1410933ff531SEduard Zingerman } 1411933ff531SEduard Zingerman 1412933ff531SEduard Zingerman if (check_expected && 1413933ff531SEduard Zingerman !find_all_insn_subseqs(buf, test->expected_insns, 1414933ff531SEduard Zingerman cnt, MAX_EXPECTED_INSNS)) { 1415933ff531SEduard Zingerman printf("FAIL: can't find expected subsequence of instructions\n"); 1416933ff531SEduard Zingerman result = false; 1417933ff531SEduard Zingerman if (verbose) { 1418933ff531SEduard Zingerman printf("Program:\n"); 1419933ff531SEduard Zingerman print_insn(buf, cnt); 1420933ff531SEduard Zingerman printf("Expected subsequence:\n"); 1421933ff531SEduard Zingerman print_insn(test->expected_insns, MAX_EXPECTED_INSNS); 1422933ff531SEduard Zingerman } 1423933ff531SEduard Zingerman } 1424933ff531SEduard Zingerman 1425933ff531SEduard Zingerman if (check_unexpected && 1426933ff531SEduard Zingerman find_all_insn_subseqs(buf, test->unexpected_insns, 1427933ff531SEduard Zingerman cnt, MAX_UNEXPECTED_INSNS)) { 1428933ff531SEduard Zingerman printf("FAIL: found unexpected subsequence of instructions\n"); 1429933ff531SEduard Zingerman result = false; 1430933ff531SEduard Zingerman if (verbose) { 1431933ff531SEduard Zingerman printf("Program:\n"); 1432933ff531SEduard Zingerman print_insn(buf, cnt); 1433933ff531SEduard Zingerman printf("Un-expected subsequence:\n"); 1434933ff531SEduard Zingerman print_insn(test->unexpected_insns, MAX_UNEXPECTED_INSNS); 1435933ff531SEduard Zingerman } 1436933ff531SEduard Zingerman } 1437933ff531SEduard Zingerman 1438933ff531SEduard Zingerman free(buf); 1439933ff531SEduard Zingerman out: 1440933ff531SEduard Zingerman return result; 1441933ff531SEduard Zingerman } 1442933ff531SEduard Zingerman 14435aa5bd14SDaniel Borkmann static void do_test_single(struct bpf_test *test, bool unpriv, 14445aa5bd14SDaniel Borkmann int *passes, int *errors) 14455aa5bd14SDaniel Borkmann { 14467a42008cSEduard Zingerman int fd_prog, btf_fd, expected_ret, alignment_prevented_execution; 144793731ef0SDaniel Borkmann int prog_len, prog_type = test->prog_type; 14485aa5bd14SDaniel Borkmann struct bpf_insn *prog = test->insns; 1449d8e86407SAndrii Nakryiko LIBBPF_OPTS(bpf_prog_load_opts, opts); 14505a8d5209SJakub Kicinski int run_errs, run_successes; 1451fb30d4b7SMartin KaFai Lau int map_fds[MAX_NR_MAPS]; 14525aa5bd14SDaniel Borkmann const char *expected_err; 14537d171672SFlorian Lehner int saved_errno; 14549acea337SStanislav Fomichev int fixup_skips; 1455c7665702SDavid Miller __u32 pflags; 1456111e6b45SAlexei Starovoitov int i, err; 14575aa5bd14SDaniel Borkmann 14587a42008cSEduard Zingerman fd_prog = -1; 1459fb30d4b7SMartin KaFai Lau for (i = 0; i < MAX_NR_MAPS; i++) 1460fb30d4b7SMartin KaFai Lau map_fds[i] = -1; 14617a42008cSEduard Zingerman btf_fd = -1; 1462fb30d4b7SMartin KaFai Lau 14630c586079SJoe Stringer if (!prog_type) 14640c586079SJoe Stringer prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 14659acea337SStanislav Fomichev fixup_skips = skips; 14660c586079SJoe Stringer do_test_fixup(test, prog_type, prog, map_fds); 14678aa2d4b4SAlexei Starovoitov if (test->fill_insns) { 14688aa2d4b4SAlexei Starovoitov prog = test->fill_insns; 14698aa2d4b4SAlexei Starovoitov prog_len = test->prog_len; 14708aa2d4b4SAlexei Starovoitov } else { 14718aa2d4b4SAlexei Starovoitov prog_len = probe_filter_length(prog); 14728aa2d4b4SAlexei Starovoitov } 14739acea337SStanislav Fomichev /* If there were some map skips during fixup due to missing bpf 14749acea337SStanislav Fomichev * features, skip this test. 14759acea337SStanislav Fomichev */ 14769acea337SStanislav Fomichev if (fixup_skips != skips) 14779acea337SStanislav Fomichev return; 14785aa5bd14SDaniel Borkmann 14799d120b41SJiong Wang pflags = BPF_F_TEST_RND_HI32; 1480c7665702SDavid Miller if (test->flags & F_LOAD_WITH_STRICT_ALIGNMENT) 1481c7665702SDavid Miller pflags |= BPF_F_STRICT_ALIGNMENT; 1482c7665702SDavid Miller if (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) 1483c7665702SDavid Miller pflags |= BPF_F_ANY_ALIGNMENT; 1484e8c13c4dSAlexei Starovoitov if (test->flags & ~3) 1485e8c13c4dSAlexei Starovoitov pflags |= test->flags; 148676d95077SStanislav Fomichev 1487e8c13c4dSAlexei Starovoitov expected_ret = unpriv && test->result_unpriv != UNDEF ? 1488e8c13c4dSAlexei Starovoitov test->result_unpriv : test->result; 1489e8c13c4dSAlexei Starovoitov expected_err = unpriv && test->errstr_unpriv ? 1490e8c13c4dSAlexei Starovoitov test->errstr_unpriv : test->errstr; 1491d8e86407SAndrii Nakryiko 1492d8e86407SAndrii Nakryiko opts.expected_attach_type = test->expected_attach_type; 14936f8a57ccSAndrii Nakryiko if (verbose) 14942a72f595SAndrii Nakryiko opts.log_level = verif_log_level | 4; /* force stats */ 14956f8a57ccSAndrii Nakryiko else if (expected_ret == VERBOSE_ACCEPT) 1496d8e86407SAndrii Nakryiko opts.log_level = 2; 14976f8a57ccSAndrii Nakryiko else 14987a42008cSEduard Zingerman opts.log_level = DEFAULT_LIBBPF_LOG_LEVEL; 1499d8e86407SAndrii Nakryiko opts.prog_flags = pflags; 150076d95077SStanislav Fomichev 15017c036ed9SRoberto Sassu if ((prog_type == BPF_PROG_TYPE_TRACING || 15027c036ed9SRoberto Sassu prog_type == BPF_PROG_TYPE_LSM) && test->kfunc) { 1503d8e86407SAndrii Nakryiko int attach_btf_id; 1504d8e86407SAndrii Nakryiko 1505d8e86407SAndrii Nakryiko attach_btf_id = libbpf_find_vmlinux_btf_id(test->kfunc, 1506d8e86407SAndrii Nakryiko opts.expected_attach_type); 1507d8e86407SAndrii Nakryiko if (attach_btf_id < 0) { 1508762f8515SJiri Olsa printf("FAIL\nFailed to find BTF ID for '%s'!\n", 1509762f8515SJiri Olsa test->kfunc); 1510762f8515SJiri Olsa (*errors)++; 1511762f8515SJiri Olsa return; 1512762f8515SJiri Olsa } 1513d8e86407SAndrii Nakryiko 1514d8e86407SAndrii Nakryiko opts.attach_btf_id = attach_btf_id; 1515762f8515SJiri Olsa } 1516762f8515SJiri Olsa 15177a42008cSEduard Zingerman if (test->btf_types[0] != 0) { 15187a42008cSEduard Zingerman btf_fd = load_btf_for_test(test); 15197a42008cSEduard Zingerman if (btf_fd < 0) 15207a42008cSEduard Zingerman goto fail_log; 15217a42008cSEduard Zingerman opts.prog_btf_fd = btf_fd; 15227a42008cSEduard Zingerman } 15237a42008cSEduard Zingerman 15247a42008cSEduard Zingerman if (test->func_info_cnt != 0) { 15257a42008cSEduard Zingerman opts.func_info = test->func_info; 15267a42008cSEduard Zingerman opts.func_info_cnt = test->func_info_cnt; 15277a42008cSEduard Zingerman opts.func_info_rec_size = sizeof(test->func_info[0]); 15287a42008cSEduard Zingerman } 15297a42008cSEduard Zingerman 1530d8e86407SAndrii Nakryiko opts.log_buf = bpf_vlog; 1531d8e86407SAndrii Nakryiko opts.log_size = sizeof(bpf_vlog); 1532d8e86407SAndrii Nakryiko fd_prog = bpf_prog_load(prog_type, NULL, "GPL", prog, prog_len, &opts); 15337d171672SFlorian Lehner saved_errno = errno; 1534762f8515SJiri Olsa 1535762f8515SJiri Olsa /* BPF_PROG_TYPE_TRACING requires more setup and 1536762f8515SJiri Olsa * bpf_probe_prog_type won't give correct answer 1537762f8515SJiri Olsa */ 1538762f8515SJiri Olsa if (fd_prog < 0 && prog_type != BPF_PROG_TYPE_TRACING && 153932e608f8SAndrii Nakryiko !libbpf_probe_bpf_prog_type(prog_type, NULL)) { 15408184d44cSStanislav Fomichev printf("SKIP (unsupported program type %d)\n", prog_type); 15418184d44cSStanislav Fomichev skips++; 15428184d44cSStanislav Fomichev goto close_fds; 15438184d44cSStanislav Fomichev } 15445aa5bd14SDaniel Borkmann 15455319255bSIlya Leoshkevich if (fd_prog < 0 && saved_errno == ENOTSUPP) { 15465319255bSIlya Leoshkevich printf("SKIP (program uses an unsupported feature)\n"); 15475319255bSIlya Leoshkevich skips++; 15485319255bSIlya Leoshkevich goto close_fds; 15495319255bSIlya Leoshkevich } 15505319255bSIlya Leoshkevich 1551c7665702SDavid Miller alignment_prevented_execution = 0; 1552c7665702SDavid Miller 1553e8c13c4dSAlexei Starovoitov if (expected_ret == ACCEPT || expected_ret == VERBOSE_ACCEPT) { 1554c7665702SDavid Miller if (fd_prog < 0) { 15555aa5bd14SDaniel Borkmann printf("FAIL\nFailed to load prog '%s'!\n", 15567d171672SFlorian Lehner strerror(saved_errno)); 15575aa5bd14SDaniel Borkmann goto fail_log; 15585aa5bd14SDaniel Borkmann } 1559c7665702SDavid Miller #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1560c7665702SDavid Miller if (fd_prog >= 0 && 15615a8d5209SJakub Kicinski (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS)) 1562c7665702SDavid Miller alignment_prevented_execution = 1; 1563c7665702SDavid Miller #endif 1564e8c13c4dSAlexei Starovoitov if (expected_ret == VERBOSE_ACCEPT && !cmp_str_seq(bpf_vlog, expected_err)) { 1565e8c13c4dSAlexei Starovoitov goto fail_log; 1566e8c13c4dSAlexei Starovoitov } 15675aa5bd14SDaniel Borkmann } else { 15685aa5bd14SDaniel Borkmann if (fd_prog >= 0) { 15695aa5bd14SDaniel Borkmann printf("FAIL\nUnexpected success to load!\n"); 15705aa5bd14SDaniel Borkmann goto fail_log; 15715aa5bd14SDaniel Borkmann } 1572060fd103SAndrei Matei if (!expected_err || !cmp_str_seq(bpf_vlog, expected_err)) { 157395f87a97SJoe Stringer printf("FAIL\nUnexpected error message!\n\tEXP: %s\n\tRES: %s\n", 157495f87a97SJoe Stringer expected_err, bpf_vlog); 15755aa5bd14SDaniel Borkmann goto fail_log; 15765aa5bd14SDaniel Borkmann } 15775aa5bd14SDaniel Borkmann } 15785aa5bd14SDaniel Borkmann 1579973377ffSDaniel Borkmann if (!unpriv && test->insn_processed) { 1580730ff40fSAlexei Starovoitov uint32_t insn_processed; 1581730ff40fSAlexei Starovoitov char *proc; 15826e6fddc7SDaniel Borkmann 1583730ff40fSAlexei Starovoitov proc = strstr(bpf_vlog, "processed "); 1584730ff40fSAlexei Starovoitov insn_processed = atoi(proc + 10); 1585730ff40fSAlexei Starovoitov if (test->insn_processed != insn_processed) { 1586730ff40fSAlexei Starovoitov printf("FAIL\nUnexpected insn_processed %u vs %u\n", 1587730ff40fSAlexei Starovoitov insn_processed, test->insn_processed); 1588111e6b45SAlexei Starovoitov goto fail_log; 1589111e6b45SAlexei Starovoitov } 1590111e6b45SAlexei Starovoitov } 1591730ff40fSAlexei Starovoitov 1592e8c13c4dSAlexei Starovoitov if (verbose) 1593e8c13c4dSAlexei Starovoitov printf(", verifier log:\n%s", bpf_vlog); 1594e8c13c4dSAlexei Starovoitov 1595933ff531SEduard Zingerman if (!check_xlated_program(test, fd_prog)) 1596933ff531SEduard Zingerman goto fail_log; 1597933ff531SEduard Zingerman 15985a8d5209SJakub Kicinski run_errs = 0; 15995a8d5209SJakub Kicinski run_successes = 0; 1600b4f89463SLorenz Bauer if (!alignment_prevented_execution && fd_prog >= 0 && test->runs >= 0) { 16015a8d5209SJakub Kicinski uint32_t expected_val; 16025a8d5209SJakub Kicinski int i; 16035aa5bd14SDaniel Borkmann 1604d5e1db99SAndrii Nakryiko if (!test->runs) 1605d5e1db99SAndrii Nakryiko test->runs = 1; 16065a8d5209SJakub Kicinski 16075a8d5209SJakub Kicinski for (i = 0; i < test->runs; i++) { 16085a8d5209SJakub Kicinski if (unpriv && test->retvals[i].retval_unpriv) 16095a8d5209SJakub Kicinski expected_val = test->retvals[i].retval_unpriv; 16105a8d5209SJakub Kicinski else 16115a8d5209SJakub Kicinski expected_val = test->retvals[i].retval; 16125a8d5209SJakub Kicinski 16135a8d5209SJakub Kicinski err = do_prog_test_run(fd_prog, unpriv, expected_val, 16145a8d5209SJakub Kicinski test->retvals[i].data, 16155a8d5209SJakub Kicinski sizeof(test->retvals[i].data)); 16165a8d5209SJakub Kicinski if (err) { 16175a8d5209SJakub Kicinski printf("(run %d/%d) ", i + 1, test->runs); 16185a8d5209SJakub Kicinski run_errs++; 16195a8d5209SJakub Kicinski } else { 16205a8d5209SJakub Kicinski run_successes++; 16215aa5bd14SDaniel Borkmann } 16225aa5bd14SDaniel Borkmann } 16235a8d5209SJakub Kicinski } 16245a8d5209SJakub Kicinski 16255a8d5209SJakub Kicinski if (!run_errs) { 16265aa5bd14SDaniel Borkmann (*passes)++; 16275a8d5209SJakub Kicinski if (run_successes > 1) 16285a8d5209SJakub Kicinski printf("%d cases ", run_successes); 16295a8d5209SJakub Kicinski printf("OK"); 16305a8d5209SJakub Kicinski if (alignment_prevented_execution) 16315a8d5209SJakub Kicinski printf(" (NOTE: not executed due to unknown alignment)"); 16325a8d5209SJakub Kicinski printf("\n"); 16335a8d5209SJakub Kicinski } else { 16345a8d5209SJakub Kicinski printf("\n"); 16355a8d5209SJakub Kicinski goto fail_log; 16365a8d5209SJakub Kicinski } 16375aa5bd14SDaniel Borkmann close_fds: 16388aa2d4b4SAlexei Starovoitov if (test->fill_insns) 16398aa2d4b4SAlexei Starovoitov free(test->fill_insns); 16405aa5bd14SDaniel Borkmann close(fd_prog); 16417a42008cSEduard Zingerman close(btf_fd); 16425aa5bd14SDaniel Borkmann for (i = 0; i < MAX_NR_MAPS; i++) 16435aa5bd14SDaniel Borkmann close(map_fds[i]); 16445aa5bd14SDaniel Borkmann sched_yield(); 16455aa5bd14SDaniel Borkmann return; 16465aa5bd14SDaniel Borkmann fail_log: 16475aa5bd14SDaniel Borkmann (*errors)++; 16485aa5bd14SDaniel Borkmann printf("%s", bpf_vlog); 16495aa5bd14SDaniel Borkmann goto close_fds; 16505aa5bd14SDaniel Borkmann } 16515aa5bd14SDaniel Borkmann 16525aa5bd14SDaniel Borkmann static bool is_admin(void) 16535aa5bd14SDaniel Borkmann { 1654b1c2768aSMartin KaFai Lau __u64 caps; 16555aa5bd14SDaniel Borkmann 1656b1c2768aSMartin KaFai Lau /* The test checks for finer cap as CAP_NET_ADMIN, 1657b1c2768aSMartin KaFai Lau * CAP_PERFMON, and CAP_BPF instead of CAP_SYS_ADMIN. 1658b1c2768aSMartin KaFai Lau * Thus, disable CAP_SYS_ADMIN at the beginning. 1659b1c2768aSMartin KaFai Lau */ 1660b1c2768aSMartin KaFai Lau if (cap_disable_effective(1ULL << CAP_SYS_ADMIN, &caps)) { 1661b1c2768aSMartin KaFai Lau perror("cap_disable_effective(CAP_SYS_ADMIN)"); 16625aa5bd14SDaniel Borkmann return false; 16635aa5bd14SDaniel Borkmann } 1664b1c2768aSMartin KaFai Lau 1665b1c2768aSMartin KaFai Lau return (caps & ADMIN_CAPS) == ADMIN_CAPS; 16665aa5bd14SDaniel Borkmann } 16675aa5bd14SDaniel Borkmann 16680a674874SJoe Stringer static void get_unpriv_disabled() 16690a674874SJoe Stringer { 16700a674874SJoe Stringer char buf[2]; 16710a674874SJoe Stringer FILE *fd; 16720a674874SJoe Stringer 16730a674874SJoe Stringer fd = fopen("/proc/sys/"UNPRIV_SYSCTL, "r"); 1674deea8122SJesper Dangaard Brouer if (!fd) { 1675deea8122SJesper Dangaard Brouer perror("fopen /proc/sys/"UNPRIV_SYSCTL); 1676deea8122SJesper Dangaard Brouer unpriv_disabled = true; 1677deea8122SJesper Dangaard Brouer return; 1678deea8122SJesper Dangaard Brouer } 16790a674874SJoe Stringer if (fgets(buf, 2, fd) == buf && atoi(buf)) 16800a674874SJoe Stringer unpriv_disabled = true; 16810a674874SJoe Stringer fclose(fd); 16820a674874SJoe Stringer } 16830a674874SJoe Stringer 168436641ad6SDaniel Borkmann static bool test_as_unpriv(struct bpf_test *test) 168536641ad6SDaniel Borkmann { 1686c77b0589SBjörn Töpel #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1687c77b0589SBjörn Töpel /* Some architectures have strict alignment requirements. In 1688c77b0589SBjörn Töpel * that case, the BPF verifier detects if a program has 1689c77b0589SBjörn Töpel * unaligned accesses and rejects them. A user can pass 1690c77b0589SBjörn Töpel * BPF_F_ANY_ALIGNMENT to a program to override this 1691c77b0589SBjörn Töpel * check. That, however, will only work when a privileged user 1692c77b0589SBjörn Töpel * loads a program. An unprivileged user loading a program 1693c77b0589SBjörn Töpel * with this flag will be rejected prior entering the 1694c77b0589SBjörn Töpel * verifier. 1695c77b0589SBjörn Töpel */ 1696c77b0589SBjörn Töpel if (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) 1697c77b0589SBjörn Töpel return false; 1698c77b0589SBjörn Töpel #endif 169936641ad6SDaniel Borkmann return !test->prog_type || 170036641ad6SDaniel Borkmann test->prog_type == BPF_PROG_TYPE_SOCKET_FILTER || 170136641ad6SDaniel Borkmann test->prog_type == BPF_PROG_TYPE_CGROUP_SKB; 170236641ad6SDaniel Borkmann } 170336641ad6SDaniel Borkmann 17045aa5bd14SDaniel Borkmann static int do_test(bool unpriv, unsigned int from, unsigned int to) 17055aa5bd14SDaniel Borkmann { 17068184d44cSStanislav Fomichev int i, passes = 0, errors = 0; 17075aa5bd14SDaniel Borkmann 17085aa5bd14SDaniel Borkmann for (i = from; i < to; i++) { 17095aa5bd14SDaniel Borkmann struct bpf_test *test = &tests[i]; 17105aa5bd14SDaniel Borkmann 17115aa5bd14SDaniel Borkmann /* Program types that are not supported by non-root we 17125aa5bd14SDaniel Borkmann * skip right away. 17135aa5bd14SDaniel Borkmann */ 171436641ad6SDaniel Borkmann if (test_as_unpriv(test) && unpriv_disabled) { 17150a674874SJoe Stringer printf("#%d/u %s SKIP\n", i, test->descr); 17160a674874SJoe Stringer skips++; 171736641ad6SDaniel Borkmann } else if (test_as_unpriv(test)) { 17185aa5bd14SDaniel Borkmann if (!unpriv) 17195aa5bd14SDaniel Borkmann set_admin(false); 17205aa5bd14SDaniel Borkmann printf("#%d/u %s ", i, test->descr); 17215aa5bd14SDaniel Borkmann do_test_single(test, true, &passes, &errors); 17225aa5bd14SDaniel Borkmann if (!unpriv) 17235aa5bd14SDaniel Borkmann set_admin(true); 17245aa5bd14SDaniel Borkmann } 17255aa5bd14SDaniel Borkmann 1726d0a0e495SJoe Stringer if (unpriv) { 1727d0a0e495SJoe Stringer printf("#%d/p %s SKIP\n", i, test->descr); 1728d0a0e495SJoe Stringer skips++; 1729d0a0e495SJoe Stringer } else { 17305aa5bd14SDaniel Borkmann printf("#%d/p %s ", i, test->descr); 17315aa5bd14SDaniel Borkmann do_test_single(test, false, &passes, &errors); 17325aa5bd14SDaniel Borkmann } 17335aa5bd14SDaniel Borkmann } 17345aa5bd14SDaniel Borkmann 1735d0a0e495SJoe Stringer printf("Summary: %d PASSED, %d SKIPPED, %d FAILED\n", passes, 1736d0a0e495SJoe Stringer skips, errors); 17375aa5bd14SDaniel Borkmann return errors ? EXIT_FAILURE : EXIT_SUCCESS; 17385aa5bd14SDaniel Borkmann } 17395aa5bd14SDaniel Borkmann 17405aa5bd14SDaniel Borkmann int main(int argc, char **argv) 17415aa5bd14SDaniel Borkmann { 17425aa5bd14SDaniel Borkmann unsigned int from = 0, to = ARRAY_SIZE(tests); 17435aa5bd14SDaniel Borkmann bool unpriv = !is_admin(); 1744e8c13c4dSAlexei Starovoitov int arg = 1; 1745e8c13c4dSAlexei Starovoitov 1746e8c13c4dSAlexei Starovoitov if (argc > 1 && strcmp(argv[1], "-v") == 0) { 1747e8c13c4dSAlexei Starovoitov arg++; 1748e8c13c4dSAlexei Starovoitov verbose = true; 17492a72f595SAndrii Nakryiko verif_log_level = 1; 17502a72f595SAndrii Nakryiko argc--; 17512a72f595SAndrii Nakryiko } 17522a72f595SAndrii Nakryiko if (argc > 1 && strcmp(argv[1], "-vv") == 0) { 17532a72f595SAndrii Nakryiko arg++; 17542a72f595SAndrii Nakryiko verbose = true; 17552a72f595SAndrii Nakryiko verif_log_level = 2; 1756e8c13c4dSAlexei Starovoitov argc--; 1757e8c13c4dSAlexei Starovoitov } 17585aa5bd14SDaniel Borkmann 17595aa5bd14SDaniel Borkmann if (argc == 3) { 1760e8c13c4dSAlexei Starovoitov unsigned int l = atoi(argv[arg]); 1761e8c13c4dSAlexei Starovoitov unsigned int u = atoi(argv[arg + 1]); 17625aa5bd14SDaniel Borkmann 17635aa5bd14SDaniel Borkmann if (l < to && u < to) { 17645aa5bd14SDaniel Borkmann from = l; 17655aa5bd14SDaniel Borkmann to = u + 1; 17665aa5bd14SDaniel Borkmann } 17675aa5bd14SDaniel Borkmann } else if (argc == 2) { 1768e8c13c4dSAlexei Starovoitov unsigned int t = atoi(argv[arg]); 17695aa5bd14SDaniel Borkmann 17705aa5bd14SDaniel Borkmann if (t < to) { 17715aa5bd14SDaniel Borkmann from = t; 17725aa5bd14SDaniel Borkmann to = t + 1; 17735aa5bd14SDaniel Borkmann } 17745aa5bd14SDaniel Borkmann } 17755aa5bd14SDaniel Borkmann 17760a674874SJoe Stringer get_unpriv_disabled(); 17770a674874SJoe Stringer if (unpriv && unpriv_disabled) { 17780a674874SJoe Stringer printf("Cannot run as unprivileged user with sysctl %s.\n", 17790a674874SJoe Stringer UNPRIV_SYSCTL); 17800a674874SJoe Stringer return EXIT_FAILURE; 17810a674874SJoe Stringer } 17820a674874SJoe Stringer 1783c164b8b4SAndrii Nakryiko /* Use libbpf 1.0 API mode */ 1784c164b8b4SAndrii Nakryiko libbpf_set_strict_mode(LIBBPF_STRICT_ALL); 1785c164b8b4SAndrii Nakryiko 1786a82d8cd3SDaniel Borkmann bpf_semi_rand_init(); 17875aa5bd14SDaniel Borkmann return do_test(unpriv, from, to); 17885aa5bd14SDaniel Borkmann } 1789