1 #define BTF_TYPES \ 2 .btf_strings = "\0int\0i\0ctx\0callback\0main\0", \ 3 .btf_types = { \ 4 /* 1: int */ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), \ 5 /* 2: int* */ BTF_PTR_ENC(1), \ 6 /* 3: void* */ BTF_PTR_ENC(0), \ 7 /* 4: int __(void*) */ BTF_FUNC_PROTO_ENC(1, 1), \ 8 BTF_FUNC_PROTO_ARG_ENC(7, 3), \ 9 /* 5: int __(int, int*) */ BTF_FUNC_PROTO_ENC(1, 2), \ 10 BTF_FUNC_PROTO_ARG_ENC(5, 1), \ 11 BTF_FUNC_PROTO_ARG_ENC(7, 2), \ 12 /* 6: main */ BTF_FUNC_ENC(20, 4), \ 13 /* 7: callback */ BTF_FUNC_ENC(11, 5), \ 14 BTF_END_RAW \ 15 } 16 17 #define MAIN_TYPE 6 18 #define CALLBACK_TYPE 7 19 20 /* can't use BPF_CALL_REL, jit_subprogs adjusts IMM & OFF 21 * fields for pseudo calls 22 */ 23 #define PSEUDO_CALL_INSN() \ 24 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_CALL, \ 25 INSN_OFF_MASK, INSN_IMM_MASK) 26 27 /* can't use BPF_FUNC_loop constant, 28 * do_mix_fixups adjusts the IMM field 29 */ 30 #define HELPER_CALL_INSN() \ 31 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, INSN_OFF_MASK, INSN_IMM_MASK) 32 33 { 34 "inline simple bpf_loop call", 35 .insns = { 36 /* main */ 37 /* force verifier state branching to verify logic on first and 38 * subsequent bpf_loop insn processing steps 39 */ 40 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), 41 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 2), 42 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), 43 BPF_JMP_IMM(BPF_JA, 0, 0, 1), 44 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), 45 46 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6), 47 BPF_RAW_INSN(0, 0, 0, 0, 0), 48 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 49 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 50 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 51 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), 52 BPF_EXIT_INSN(), 53 /* callback */ 54 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 55 BPF_EXIT_INSN(), 56 }, 57 .expected_insns = { PSEUDO_CALL_INSN() }, 58 .unexpected_insns = { HELPER_CALL_INSN() }, 59 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 60 .result = ACCEPT, 61 .runs = 0, 62 .func_info = { { 0, MAIN_TYPE }, { 12, CALLBACK_TYPE } }, 63 .func_info_cnt = 2, 64 BTF_TYPES 65 }, 66 { 67 "don't inline bpf_loop call, flags non-zero", 68 .insns = { 69 /* main */ 70 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), 71 BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0), 72 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), 73 BPF_ALU64_REG(BPF_MOV, BPF_REG_7, BPF_REG_0), 74 BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 9), 75 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 76 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 0), 77 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), 78 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 7), 79 BPF_RAW_INSN(0, 0, 0, 0, 0), 80 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 81 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 82 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), 83 BPF_EXIT_INSN(), 84 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 1), 85 BPF_JMP_IMM(BPF_JA, 0, 0, -10), 86 /* callback */ 87 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 88 BPF_EXIT_INSN(), 89 }, 90 .expected_insns = { HELPER_CALL_INSN() }, 91 .unexpected_insns = { PSEUDO_CALL_INSN() }, 92 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 93 .result = ACCEPT, 94 .runs = 0, 95 .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } }, 96 .func_info_cnt = 2, 97 BTF_TYPES 98 }, 99 { 100 "don't inline bpf_loop call, callback non-constant", 101 .insns = { 102 /* main */ 103 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64), 104 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 777, 4), /* pick a random callback */ 105 106 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), 107 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 10), 108 BPF_RAW_INSN(0, 0, 0, 0, 0), 109 BPF_JMP_IMM(BPF_JA, 0, 0, 3), 110 111 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), 112 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8), 113 BPF_RAW_INSN(0, 0, 0, 0, 0), 114 115 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 116 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 117 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 118 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), 119 BPF_EXIT_INSN(), 120 /* callback */ 121 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 122 BPF_EXIT_INSN(), 123 /* callback #2 */ 124 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 125 BPF_EXIT_INSN(), 126 }, 127 .expected_insns = { HELPER_CALL_INSN() }, 128 .unexpected_insns = { PSEUDO_CALL_INSN() }, 129 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 130 .result = ACCEPT, 131 .runs = 0, 132 .func_info = { 133 { 0, MAIN_TYPE }, 134 { 14, CALLBACK_TYPE }, 135 { 16, CALLBACK_TYPE } 136 }, 137 .func_info_cnt = 3, 138 BTF_TYPES 139 }, 140 { 141 "bpf_loop_inline and a dead func", 142 .insns = { 143 /* main */ 144 145 /* A reference to callback #1 to make verifier count it as a func. 146 * This reference is overwritten below and callback #1 is dead. 147 */ 148 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 9), 149 BPF_RAW_INSN(0, 0, 0, 0, 0), 150 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), 151 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 8), 152 BPF_RAW_INSN(0, 0, 0, 0, 0), 153 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 154 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 155 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 156 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), 157 BPF_EXIT_INSN(), 158 /* callback */ 159 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 160 BPF_EXIT_INSN(), 161 /* callback #2 */ 162 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 163 BPF_EXIT_INSN(), 164 }, 165 .expected_insns = { PSEUDO_CALL_INSN() }, 166 .unexpected_insns = { HELPER_CALL_INSN() }, 167 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 168 .result = ACCEPT, 169 .runs = 0, 170 .func_info = { 171 { 0, MAIN_TYPE }, 172 { 10, CALLBACK_TYPE }, 173 { 12, CALLBACK_TYPE } 174 }, 175 .func_info_cnt = 3, 176 BTF_TYPES 177 }, 178 { 179 "bpf_loop_inline stack locations for loop vars", 180 .insns = { 181 /* main */ 182 BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77), 183 /* bpf_loop call #1 */ 184 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 1), 185 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 22), 186 BPF_RAW_INSN(0, 0, 0, 0, 0), 187 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 188 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 189 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 190 /* bpf_loop call #2 */ 191 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), 192 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 16), 193 BPF_RAW_INSN(0, 0, 0, 0, 0), 194 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 195 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 196 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 197 /* call func and exit */ 198 BPF_CALL_REL(2), 199 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), 200 BPF_EXIT_INSN(), 201 /* func */ 202 BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55), 203 BPF_ALU64_IMM(BPF_MOV, BPF_REG_1, 2), 204 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, BPF_REG_2, BPF_PSEUDO_FUNC, 0, 6), 205 BPF_RAW_INSN(0, 0, 0, 0, 0), 206 BPF_ALU64_IMM(BPF_MOV, BPF_REG_3, 0), 207 BPF_ALU64_IMM(BPF_MOV, BPF_REG_4, 0), 208 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_loop), 209 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), 210 BPF_EXIT_INSN(), 211 /* callback */ 212 BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 1), 213 BPF_EXIT_INSN(), 214 }, 215 .expected_insns = { 216 BPF_ST_MEM(BPF_W, BPF_REG_10, -12, 0x77), 217 SKIP_INSNS(), 218 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40), 219 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32), 220 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24), 221 SKIP_INSNS(), 222 /* offsets are the same as in the first call */ 223 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -40), 224 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -32), 225 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -24), 226 SKIP_INSNS(), 227 BPF_ST_MEM(BPF_DW, BPF_REG_10, -32, 0x55), 228 SKIP_INSNS(), 229 /* offsets differ from main because of different offset 230 * in BPF_ST_MEM instruction 231 */ 232 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_6, -56), 233 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_7, -48), 234 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_8, -40), 235 }, 236 .unexpected_insns = { HELPER_CALL_INSN() }, 237 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 238 .result = ACCEPT, 239 .func_info = { 240 { 0, MAIN_TYPE }, 241 { 16, MAIN_TYPE }, 242 { 25, CALLBACK_TYPE }, 243 }, 244 .func_info_cnt = 3, 245 BTF_TYPES 246 }, 247 { 248 "inline bpf_loop call in a big program", 249 .insns = {}, 250 .fill_helper = bpf_fill_big_prog_with_loop_1, 251 .expected_insns = { PSEUDO_CALL_INSN() }, 252 .unexpected_insns = { HELPER_CALL_INSN() }, 253 .result = ACCEPT, 254 .prog_type = BPF_PROG_TYPE_TRACEPOINT, 255 .func_info = { { 0, MAIN_TYPE }, { 16, CALLBACK_TYPE } }, 256 .func_info_cnt = 2, 257 BTF_TYPES 258 }, 259 260 #undef HELPER_CALL_INSN 261 #undef PSEUDO_CALL_INSN 262 #undef CALLBACK_TYPE 263 #undef MAIN_TYPE 264 #undef BTF_TYPES 265