Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: add verifier tests for bpf_call

Add extensive set of tests for bpf_call verification logic:

calls: basic sanity
calls: using r0 returned by callee
calls: callee is using r1
calls: callee using args1
calls: callee using wrong args2
calls: callee using two args
calls: callee changing pkt pointers
calls: two calls with args
calls: two calls with bad jump
calls: recursive call. test1
calls: recursive call. test2
calls: unreachable code
calls: invalid call
calls: jumping across function bodies. test1
calls: jumping across function bodies. test2
calls: call without exit
calls: call into middle of ld_imm64
calls: call into middle of other call
calls: two calls with bad fallthrough
calls: two calls with stack read
calls: two calls with stack write
calls: spill into caller stack frame
calls: two calls with stack write and void return
calls: ambiguous return value
calls: two calls that return map_value
calls: two calls that return map_value with bool condition
calls: two calls that return map_value with incorrect bool check
calls: two calls that receive map_value via arg=ptr_stack_of_caller. test1
calls: two calls that receive map_value via arg=ptr_stack_of_caller. test2
calls: two jumps that receive map_value via arg=ptr_stack_of_jumper. test3
calls: two calls that receive map_value_ptr_or_null via arg. test1
calls: two calls that receive map_value_ptr_or_null via arg. test2
calls: pkt_ptr spill into caller stack

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Alexei Starovoitov and committed by
Daniel Borkmann
a7ff3eca f4d7e40a

+960 -1
+960 -1
tools/testing/selftests/bpf/test_verifier.c
··· 2 2 * Testsuite for eBPF verifier 3 3 * 4 4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 5 + * Copyright (c) 2017 Facebook 5 6 * 6 7 * This program is free software; you can redistribute it and/or 7 8 * modify it under the terms of version 2 of the GNU General Public ··· 278 277 .insns = { 279 278 BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2), 280 279 }, 281 - .errstr = "jump out of range", 280 + .errstr = "not an exit", 282 281 .result = REJECT, 283 282 }, 284 283 { ··· 8097 8096 .errstr = "R0 has unknown scalar value", 8098 8097 .result = REJECT, 8099 8098 .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 8099 + }, 8100 + { 8101 + "calls: basic sanity", 8102 + .insns = { 8103 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8104 + BPF_MOV64_IMM(BPF_REG_0, 1), 8105 + BPF_EXIT_INSN(), 8106 + BPF_MOV64_IMM(BPF_REG_0, 2), 8107 + BPF_EXIT_INSN(), 8108 + }, 8109 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8110 + .result = ACCEPT, 8111 + }, 8112 + { 8113 + "calls: using r0 returned by callee", 8114 + .insns = { 8115 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8116 + BPF_EXIT_INSN(), 8117 + BPF_MOV64_IMM(BPF_REG_0, 2), 8118 + BPF_EXIT_INSN(), 8119 + }, 8120 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8121 + .result = ACCEPT, 8122 + }, 8123 + { 8124 + "calls: callee is using r1", 8125 + .insns = { 8126 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8127 + BPF_EXIT_INSN(), 8128 + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 8129 + offsetof(struct __sk_buff, len)), 8130 + BPF_EXIT_INSN(), 8131 + }, 8132 + .prog_type = BPF_PROG_TYPE_SCHED_ACT, 8133 + .result = ACCEPT, 8134 + }, 8135 + { 8136 + "calls: callee using args1", 8137 + .insns = { 8138 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8139 + BPF_EXIT_INSN(), 8140 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 8141 + BPF_EXIT_INSN(), 8142 + }, 8143 + .errstr_unpriv = "allowed for root only", 8144 + .result_unpriv = REJECT, 8145 + .result = ACCEPT, 8146 + }, 8147 + { 8148 + "calls: callee using wrong args2", 8149 + .insns = { 8150 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8151 + BPF_EXIT_INSN(), 8152 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 8153 + BPF_EXIT_INSN(), 8154 + }, 8155 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8156 + .errstr = "R2 !read_ok", 8157 + .result = REJECT, 8158 + }, 8159 + { 8160 + "calls: callee using two args", 8161 + .insns = { 8162 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8163 + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, 8164 + offsetof(struct __sk_buff, len)), 8165 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_6, 8166 + offsetof(struct __sk_buff, len)), 8167 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8168 + BPF_EXIT_INSN(), 8169 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 8170 + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2), 8171 + BPF_EXIT_INSN(), 8172 + }, 8173 + .errstr_unpriv = "allowed for root only", 8174 + .result_unpriv = REJECT, 8175 + .result = ACCEPT, 8176 + }, 8177 + { 8178 + "calls: callee changing pkt pointers", 8179 + .insns = { 8180 + BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1, 8181 + offsetof(struct xdp_md, data)), 8182 + BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, 8183 + offsetof(struct xdp_md, data_end)), 8184 + BPF_MOV64_REG(BPF_REG_8, BPF_REG_6), 8185 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 8), 8186 + BPF_JMP_REG(BPF_JGT, BPF_REG_8, BPF_REG_7, 2), 8187 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8188 + /* clear_all_pkt_pointers() has to walk all frames 8189 + * to make sure that pkt pointers in the caller 8190 + * are cleared when callee is calling a helper that 8191 + * adjusts packet size 8192 + */ 8193 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), 8194 + BPF_MOV32_IMM(BPF_REG_0, 0), 8195 + BPF_EXIT_INSN(), 8196 + BPF_MOV64_IMM(BPF_REG_2, 0), 8197 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8198 + BPF_FUNC_xdp_adjust_head), 8199 + BPF_EXIT_INSN(), 8200 + }, 8201 + .result = REJECT, 8202 + .errstr = "R6 invalid mem access 'inv'", 8203 + .prog_type = BPF_PROG_TYPE_XDP, 8204 + }, 8205 + { 8206 + "calls: two calls with args", 8207 + .insns = { 8208 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8209 + BPF_EXIT_INSN(), 8210 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8211 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 6), 8212 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 8213 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8214 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8215 + BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), 8216 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), 8217 + BPF_EXIT_INSN(), 8218 + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 8219 + offsetof(struct __sk_buff, len)), 8220 + BPF_EXIT_INSN(), 8221 + }, 8222 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8223 + .result = ACCEPT, 8224 + }, 8225 + { 8226 + "calls: two calls with bad jump", 8227 + .insns = { 8228 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8229 + BPF_EXIT_INSN(), 8230 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8231 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 6), 8232 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 8233 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8234 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8235 + BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), 8236 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), 8237 + BPF_EXIT_INSN(), 8238 + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 8239 + offsetof(struct __sk_buff, len)), 8240 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, -3), 8241 + BPF_EXIT_INSN(), 8242 + }, 8243 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8244 + .errstr = "jump out of range from insn 11 to 9", 8245 + .result = REJECT, 8246 + }, 8247 + { 8248 + "calls: recursive call. test1", 8249 + .insns = { 8250 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8251 + BPF_EXIT_INSN(), 8252 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -1), 8253 + BPF_EXIT_INSN(), 8254 + }, 8255 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8256 + .errstr = "back-edge", 8257 + .result = REJECT, 8258 + }, 8259 + { 8260 + "calls: recursive call. test2", 8261 + .insns = { 8262 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8263 + BPF_EXIT_INSN(), 8264 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -3), 8265 + BPF_EXIT_INSN(), 8266 + }, 8267 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8268 + .errstr = "back-edge", 8269 + .result = REJECT, 8270 + }, 8271 + { 8272 + "calls: unreachable code", 8273 + .insns = { 8274 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8275 + BPF_EXIT_INSN(), 8276 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8277 + BPF_EXIT_INSN(), 8278 + BPF_MOV64_IMM(BPF_REG_0, 0), 8279 + BPF_EXIT_INSN(), 8280 + BPF_MOV64_IMM(BPF_REG_0, 0), 8281 + BPF_EXIT_INSN(), 8282 + }, 8283 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8284 + .errstr = "unreachable insn 6", 8285 + .result = REJECT, 8286 + }, 8287 + { 8288 + "calls: invalid call", 8289 + .insns = { 8290 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8291 + BPF_EXIT_INSN(), 8292 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, -4), 8293 + BPF_EXIT_INSN(), 8294 + }, 8295 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8296 + .errstr = "invalid destination", 8297 + .result = REJECT, 8298 + }, 8299 + { 8300 + "calls: jumping across function bodies. test1", 8301 + .insns = { 8302 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8303 + BPF_MOV64_IMM(BPF_REG_0, 0), 8304 + BPF_EXIT_INSN(), 8305 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3), 8306 + BPF_EXIT_INSN(), 8307 + }, 8308 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8309 + .errstr = "jump out of range", 8310 + .result = REJECT, 8311 + }, 8312 + { 8313 + "calls: jumping across function bodies. test2", 8314 + .insns = { 8315 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3), 8316 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8317 + BPF_MOV64_IMM(BPF_REG_0, 0), 8318 + BPF_EXIT_INSN(), 8319 + BPF_EXIT_INSN(), 8320 + }, 8321 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8322 + .errstr = "jump out of range", 8323 + .result = REJECT, 8324 + }, 8325 + { 8326 + "calls: call without exit", 8327 + .insns = { 8328 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8329 + BPF_EXIT_INSN(), 8330 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8331 + BPF_EXIT_INSN(), 8332 + BPF_MOV64_IMM(BPF_REG_0, 0), 8333 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -2), 8334 + }, 8335 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8336 + .errstr = "not an exit", 8337 + .result = REJECT, 8338 + }, 8339 + { 8340 + "calls: call into middle of ld_imm64", 8341 + .insns = { 8342 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8343 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8344 + BPF_MOV64_IMM(BPF_REG_0, 0), 8345 + BPF_EXIT_INSN(), 8346 + BPF_LD_IMM64(BPF_REG_0, 0), 8347 + BPF_EXIT_INSN(), 8348 + }, 8349 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8350 + .errstr = "last insn", 8351 + .result = REJECT, 8352 + }, 8353 + { 8354 + "calls: call into middle of other call", 8355 + .insns = { 8356 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8357 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8358 + BPF_MOV64_IMM(BPF_REG_0, 0), 8359 + BPF_EXIT_INSN(), 8360 + BPF_MOV64_IMM(BPF_REG_0, 0), 8361 + BPF_MOV64_IMM(BPF_REG_0, 0), 8362 + BPF_EXIT_INSN(), 8363 + }, 8364 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8365 + .errstr = "last insn", 8366 + .result = REJECT, 8367 + }, 8368 + { 8369 + "calls: two calls with bad fallthrough", 8370 + .insns = { 8371 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8372 + BPF_EXIT_INSN(), 8373 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8374 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 6), 8375 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 8376 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8377 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8378 + BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), 8379 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), 8380 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_0), 8381 + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 8382 + offsetof(struct __sk_buff, len)), 8383 + BPF_EXIT_INSN(), 8384 + }, 8385 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 8386 + .errstr = "not an exit", 8387 + .result = REJECT, 8388 + }, 8389 + { 8390 + "calls: two calls with stack read", 8391 + .insns = { 8392 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8393 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8394 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8395 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8396 + BPF_EXIT_INSN(), 8397 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8398 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 6), 8399 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 8400 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8401 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8402 + BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), 8403 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), 8404 + BPF_EXIT_INSN(), 8405 + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0), 8406 + BPF_EXIT_INSN(), 8407 + }, 8408 + .prog_type = BPF_PROG_TYPE_XDP, 8409 + .result = ACCEPT, 8410 + }, 8411 + { 8412 + "calls: two calls with stack write", 8413 + .insns = { 8414 + /* main prog */ 8415 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8416 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8417 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8418 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8419 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8420 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8421 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -16), 8422 + BPF_EXIT_INSN(), 8423 + 8424 + /* subprog 1 */ 8425 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8426 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8427 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 7), 8428 + BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), 8429 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8430 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4), 8431 + BPF_ALU64_REG(BPF_ADD, BPF_REG_8, BPF_REG_0), 8432 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_8), 8433 + /* write into stack frame of main prog */ 8434 + BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), 8435 + BPF_EXIT_INSN(), 8436 + 8437 + /* subprog 2 */ 8438 + /* read from stack frame of main prog */ 8439 + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0), 8440 + BPF_EXIT_INSN(), 8441 + }, 8442 + .prog_type = BPF_PROG_TYPE_XDP, 8443 + .result = ACCEPT, 8444 + }, 8445 + { 8446 + "calls: spill into caller stack frame", 8447 + .insns = { 8448 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8449 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8450 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8451 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8452 + BPF_EXIT_INSN(), 8453 + BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, 0), 8454 + BPF_MOV64_IMM(BPF_REG_0, 0), 8455 + BPF_EXIT_INSN(), 8456 + }, 8457 + .prog_type = BPF_PROG_TYPE_XDP, 8458 + .errstr = "cannot spill", 8459 + .result = REJECT, 8460 + }, 8461 + { 8462 + "calls: two calls with stack write and void return", 8463 + .insns = { 8464 + /* main prog */ 8465 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8466 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8467 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8468 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8469 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8470 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8471 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -16), 8472 + BPF_EXIT_INSN(), 8473 + 8474 + /* subprog 1 */ 8475 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8476 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8477 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8478 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 8479 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8480 + BPF_EXIT_INSN(), 8481 + 8482 + /* subprog 2 */ 8483 + /* write into stack frame of main prog */ 8484 + BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 0), 8485 + BPF_EXIT_INSN(), /* void return */ 8486 + }, 8487 + .prog_type = BPF_PROG_TYPE_XDP, 8488 + .result = ACCEPT, 8489 + }, 8490 + { 8491 + "calls: ambiguous return value", 8492 + .insns = { 8493 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8494 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5), 8495 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 8496 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8497 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8498 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 8499 + BPF_EXIT_INSN(), 8500 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 8501 + BPF_MOV64_IMM(BPF_REG_0, 0), 8502 + BPF_EXIT_INSN(), 8503 + }, 8504 + .errstr_unpriv = "allowed for root only", 8505 + .result_unpriv = REJECT, 8506 + .errstr = "R0 !read_ok", 8507 + .result = REJECT, 8508 + }, 8509 + { 8510 + "calls: two calls that return map_value", 8511 + .insns = { 8512 + /* main prog */ 8513 + /* pass fp-16, fp-8 into a function */ 8514 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8515 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8516 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8517 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8518 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 8), 8519 + 8520 + /* fetch map_value_ptr from the stack of this function */ 8521 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 8522 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 8523 + /* write into map value */ 8524 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8525 + /* fetch secound map_value_ptr from the stack */ 8526 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -16), 8527 + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 8528 + /* write into map value */ 8529 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8530 + BPF_MOV64_IMM(BPF_REG_0, 0), 8531 + BPF_EXIT_INSN(), 8532 + 8533 + /* subprog 1 */ 8534 + /* call 3rd function twice */ 8535 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8536 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8537 + /* first time with fp-8 */ 8538 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 8539 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 8540 + /* second time with fp-16 */ 8541 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8542 + BPF_EXIT_INSN(), 8543 + 8544 + /* subprog 2 */ 8545 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8546 + /* lookup from map */ 8547 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8548 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8549 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8550 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8551 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8552 + BPF_FUNC_map_lookup_elem), 8553 + /* write map_value_ptr into stack frame of main prog */ 8554 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8555 + BPF_MOV64_IMM(BPF_REG_0, 0), 8556 + BPF_EXIT_INSN(), /* return 0 */ 8557 + }, 8558 + .prog_type = BPF_PROG_TYPE_XDP, 8559 + .fixup_map1 = { 23 }, 8560 + .result = ACCEPT, 8561 + }, 8562 + { 8563 + "calls: two calls that return map_value with bool condition", 8564 + .insns = { 8565 + /* main prog */ 8566 + /* pass fp-16, fp-8 into a function */ 8567 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8568 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8569 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8570 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8571 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8572 + BPF_MOV64_IMM(BPF_REG_0, 0), 8573 + BPF_EXIT_INSN(), 8574 + 8575 + /* subprog 1 */ 8576 + /* call 3rd function twice */ 8577 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8578 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8579 + /* first time with fp-8 */ 8580 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 9), 8581 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 1, 2), 8582 + /* fetch map_value_ptr from the stack of this function */ 8583 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), 8584 + /* write into map value */ 8585 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8586 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 8587 + /* second time with fp-16 */ 8588 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4), 8589 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 1, 2), 8590 + /* fetch secound map_value_ptr from the stack */ 8591 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7, 0), 8592 + /* write into map value */ 8593 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8594 + BPF_EXIT_INSN(), 8595 + 8596 + /* subprog 2 */ 8597 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8598 + /* lookup from map */ 8599 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8600 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8601 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8602 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8603 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8604 + BPF_FUNC_map_lookup_elem), 8605 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8606 + BPF_MOV64_IMM(BPF_REG_0, 0), 8607 + BPF_EXIT_INSN(), /* return 0 */ 8608 + /* write map_value_ptr into stack frame of main prog */ 8609 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8610 + BPF_MOV64_IMM(BPF_REG_0, 1), 8611 + BPF_EXIT_INSN(), /* return 1 */ 8612 + }, 8613 + .prog_type = BPF_PROG_TYPE_XDP, 8614 + .fixup_map1 = { 23 }, 8615 + .result = ACCEPT, 8616 + }, 8617 + { 8618 + "calls: two calls that return map_value with incorrect bool check", 8619 + .insns = { 8620 + /* main prog */ 8621 + /* pass fp-16, fp-8 into a function */ 8622 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8623 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8624 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8625 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8626 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8627 + BPF_MOV64_IMM(BPF_REG_0, 0), 8628 + BPF_EXIT_INSN(), 8629 + 8630 + /* subprog 1 */ 8631 + /* call 3rd function twice */ 8632 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8633 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8634 + /* first time with fp-8 */ 8635 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 9), 8636 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 1, 2), 8637 + /* fetch map_value_ptr from the stack of this function */ 8638 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_6, 0), 8639 + /* write into map value */ 8640 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8641 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 8642 + /* second time with fp-16 */ 8643 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4), 8644 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8645 + /* fetch secound map_value_ptr from the stack */ 8646 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7, 0), 8647 + /* write into map value */ 8648 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8649 + BPF_EXIT_INSN(), 8650 + 8651 + /* subprog 2 */ 8652 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8653 + /* lookup from map */ 8654 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8655 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8656 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8657 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8658 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8659 + BPF_FUNC_map_lookup_elem), 8660 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8661 + BPF_MOV64_IMM(BPF_REG_0, 0), 8662 + BPF_EXIT_INSN(), /* return 0 */ 8663 + /* write map_value_ptr into stack frame of main prog */ 8664 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8665 + BPF_MOV64_IMM(BPF_REG_0, 1), 8666 + BPF_EXIT_INSN(), /* return 1 */ 8667 + }, 8668 + .prog_type = BPF_PROG_TYPE_XDP, 8669 + .fixup_map1 = { 23 }, 8670 + .result = REJECT, 8671 + .errstr = "invalid read from stack off -16+0 size 8", 8672 + }, 8673 + { 8674 + "calls: two calls that receive map_value via arg=ptr_stack_of_caller. test1", 8675 + .insns = { 8676 + /* main prog */ 8677 + /* pass fp-16, fp-8 into a function */ 8678 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8679 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8680 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8681 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8682 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8683 + BPF_MOV64_IMM(BPF_REG_0, 0), 8684 + BPF_EXIT_INSN(), 8685 + 8686 + /* subprog 1 */ 8687 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8688 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8689 + /* 1st lookup from map */ 8690 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8691 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8692 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8693 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8694 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8695 + BPF_FUNC_map_lookup_elem), 8696 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8697 + BPF_MOV64_IMM(BPF_REG_8, 0), 8698 + BPF_JMP_IMM(BPF_JA, 0, 0, 2), 8699 + /* write map_value_ptr into stack frame of main prog at fp-8 */ 8700 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8701 + BPF_MOV64_IMM(BPF_REG_8, 1), 8702 + 8703 + /* 2nd lookup from map */ 8704 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* 20 */ 8705 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8706 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8707 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, /* 24 */ 8708 + BPF_FUNC_map_lookup_elem), 8709 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8710 + BPF_MOV64_IMM(BPF_REG_9, 0), 8711 + BPF_JMP_IMM(BPF_JA, 0, 0, 2), 8712 + /* write map_value_ptr into stack frame of main prog at fp-16 */ 8713 + BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), 8714 + BPF_MOV64_IMM(BPF_REG_9, 1), 8715 + 8716 + /* call 3rd func with fp-8, 0|1, fp-16, 0|1 */ 8717 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), /* 30 */ 8718 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_8), 8719 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_7), 8720 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_9), 8721 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), /* 34 */ 8722 + BPF_EXIT_INSN(), 8723 + 8724 + /* subprog 2 */ 8725 + /* if arg2 == 1 do *arg1 = 0 */ 8726 + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 1, 2), 8727 + /* fetch map_value_ptr from the stack of this function */ 8728 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), 8729 + /* write into map value */ 8730 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8731 + 8732 + /* if arg4 == 1 do *arg3 = 0 */ 8733 + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 1, 2), 8734 + /* fetch map_value_ptr from the stack of this function */ 8735 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), 8736 + /* write into map value */ 8737 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 2, 0), 8738 + BPF_EXIT_INSN(), 8739 + }, 8740 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8741 + .fixup_map1 = { 12, 22 }, 8742 + .result = REJECT, 8743 + .errstr = "invalid access to map value, value_size=8 off=2 size=8", 8744 + }, 8745 + { 8746 + "calls: two calls that receive map_value via arg=ptr_stack_of_caller. test2", 8747 + .insns = { 8748 + /* main prog */ 8749 + /* pass fp-16, fp-8 into a function */ 8750 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8751 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8752 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8753 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8754 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8755 + BPF_MOV64_IMM(BPF_REG_0, 0), 8756 + BPF_EXIT_INSN(), 8757 + 8758 + /* subprog 1 */ 8759 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8760 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8761 + /* 1st lookup from map */ 8762 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8763 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8764 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8765 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8766 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8767 + BPF_FUNC_map_lookup_elem), 8768 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8769 + BPF_MOV64_IMM(BPF_REG_8, 0), 8770 + BPF_JMP_IMM(BPF_JA, 0, 0, 2), 8771 + /* write map_value_ptr into stack frame of main prog at fp-8 */ 8772 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8773 + BPF_MOV64_IMM(BPF_REG_8, 1), 8774 + 8775 + /* 2nd lookup from map */ 8776 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* 20 */ 8777 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8778 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8779 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, /* 24 */ 8780 + BPF_FUNC_map_lookup_elem), 8781 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8782 + BPF_MOV64_IMM(BPF_REG_9, 0), 8783 + BPF_JMP_IMM(BPF_JA, 0, 0, 2), 8784 + /* write map_value_ptr into stack frame of main prog at fp-16 */ 8785 + BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), 8786 + BPF_MOV64_IMM(BPF_REG_9, 1), 8787 + 8788 + /* call 3rd func with fp-8, 0|1, fp-16, 0|1 */ 8789 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), /* 30 */ 8790 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_8), 8791 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_7), 8792 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_9), 8793 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), /* 34 */ 8794 + BPF_EXIT_INSN(), 8795 + 8796 + /* subprog 2 */ 8797 + /* if arg2 == 1 do *arg1 = 0 */ 8798 + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 1, 2), 8799 + /* fetch map_value_ptr from the stack of this function */ 8800 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), 8801 + /* write into map value */ 8802 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8803 + 8804 + /* if arg4 == 1 do *arg3 = 0 */ 8805 + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 1, 2), 8806 + /* fetch map_value_ptr from the stack of this function */ 8807 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), 8808 + /* write into map value */ 8809 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8810 + BPF_EXIT_INSN(), 8811 + }, 8812 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8813 + .fixup_map1 = { 12, 22 }, 8814 + .result = ACCEPT, 8815 + }, 8816 + { 8817 + "calls: two jumps that receive map_value via arg=ptr_stack_of_jumper. test3", 8818 + .insns = { 8819 + /* main prog */ 8820 + /* pass fp-16, fp-8 into a function */ 8821 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8822 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8823 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8824 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8825 + BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2), 8826 + BPF_MOV64_IMM(BPF_REG_0, 0), 8827 + BPF_EXIT_INSN(), 8828 + 8829 + /* subprog 1 */ 8830 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8831 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8832 + /* 1st lookup from map */ 8833 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -24, 0), 8834 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8835 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -24), 8836 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8837 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8838 + BPF_FUNC_map_lookup_elem), 8839 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8840 + BPF_MOV64_IMM(BPF_REG_8, 0), 8841 + BPF_JMP_IMM(BPF_JA, 0, 0, 2), 8842 + /* write map_value_ptr into stack frame of main prog at fp-8 */ 8843 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8844 + BPF_MOV64_IMM(BPF_REG_8, 1), 8845 + 8846 + /* 2nd lookup from map */ 8847 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8848 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -24), 8849 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8850 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8851 + BPF_FUNC_map_lookup_elem), 8852 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8853 + BPF_MOV64_IMM(BPF_REG_9, 0), // 26 8854 + BPF_JMP_IMM(BPF_JA, 0, 0, 2), 8855 + /* write map_value_ptr into stack frame of main prog at fp-16 */ 8856 + BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), 8857 + BPF_MOV64_IMM(BPF_REG_9, 1), 8858 + 8859 + /* call 3rd func with fp-8, 0|1, fp-16, 0|1 */ 8860 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), // 30 8861 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_8), 8862 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_7), 8863 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_9), 8864 + BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1), // 34 8865 + BPF_JMP_IMM(BPF_JA, 0, 0, -30), 8866 + 8867 + /* subprog 2 */ 8868 + /* if arg2 == 1 do *arg1 = 0 */ 8869 + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 1, 2), 8870 + /* fetch map_value_ptr from the stack of this function */ 8871 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), 8872 + /* write into map value */ 8873 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8874 + 8875 + /* if arg4 == 1 do *arg3 = 0 */ 8876 + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 1, 2), 8877 + /* fetch map_value_ptr from the stack of this function */ 8878 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), 8879 + /* write into map value */ 8880 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 2, 0), 8881 + BPF_JMP_IMM(BPF_JA, 0, 0, -8), 8882 + }, 8883 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8884 + .fixup_map1 = { 12, 22 }, 8885 + .result = REJECT, 8886 + .errstr = "invalid access to map value, value_size=8 off=2 size=8", 8887 + }, 8888 + { 8889 + "calls: two calls that receive map_value_ptr_or_null via arg. test1", 8890 + .insns = { 8891 + /* main prog */ 8892 + /* pass fp-16, fp-8 into a function */ 8893 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8894 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8895 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8896 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8897 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8898 + BPF_MOV64_IMM(BPF_REG_0, 0), 8899 + BPF_EXIT_INSN(), 8900 + 8901 + /* subprog 1 */ 8902 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8903 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8904 + /* 1st lookup from map */ 8905 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8906 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8907 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8908 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8909 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8910 + BPF_FUNC_map_lookup_elem), 8911 + /* write map_value_ptr_or_null into stack frame of main prog at fp-8 */ 8912 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8913 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8914 + BPF_MOV64_IMM(BPF_REG_8, 0), 8915 + BPF_JMP_IMM(BPF_JA, 0, 0, 1), 8916 + BPF_MOV64_IMM(BPF_REG_8, 1), 8917 + 8918 + /* 2nd lookup from map */ 8919 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8920 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8921 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8922 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8923 + BPF_FUNC_map_lookup_elem), 8924 + /* write map_value_ptr_or_null into stack frame of main prog at fp-16 */ 8925 + BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), 8926 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8927 + BPF_MOV64_IMM(BPF_REG_9, 0), 8928 + BPF_JMP_IMM(BPF_JA, 0, 0, 1), 8929 + BPF_MOV64_IMM(BPF_REG_9, 1), 8930 + 8931 + /* call 3rd func with fp-8, 0|1, fp-16, 0|1 */ 8932 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 8933 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_8), 8934 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_7), 8935 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_9), 8936 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 8937 + BPF_EXIT_INSN(), 8938 + 8939 + /* subprog 2 */ 8940 + /* if arg2 == 1 do *arg1 = 0 */ 8941 + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 1, 2), 8942 + /* fetch map_value_ptr from the stack of this function */ 8943 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), 8944 + /* write into map value */ 8945 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8946 + 8947 + /* if arg4 == 1 do *arg3 = 0 */ 8948 + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 1, 2), 8949 + /* fetch map_value_ptr from the stack of this function */ 8950 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), 8951 + /* write into map value */ 8952 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 8953 + BPF_EXIT_INSN(), 8954 + }, 8955 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8956 + .fixup_map1 = { 12, 22 }, 8957 + .result = ACCEPT, 8958 + }, 8959 + { 8960 + "calls: two calls that receive map_value_ptr_or_null via arg. test2", 8961 + .insns = { 8962 + /* main prog */ 8963 + /* pass fp-16, fp-8 into a function */ 8964 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 8965 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 8966 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8967 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 8968 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 8969 + BPF_MOV64_IMM(BPF_REG_0, 0), 8970 + BPF_EXIT_INSN(), 8971 + 8972 + /* subprog 1 */ 8973 + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 8974 + BPF_MOV64_REG(BPF_REG_7, BPF_REG_2), 8975 + /* 1st lookup from map */ 8976 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 8977 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8978 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8979 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8980 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8981 + BPF_FUNC_map_lookup_elem), 8982 + /* write map_value_ptr_or_null into stack frame of main prog at fp-8 */ 8983 + BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 8984 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8985 + BPF_MOV64_IMM(BPF_REG_8, 0), 8986 + BPF_JMP_IMM(BPF_JA, 0, 0, 1), 8987 + BPF_MOV64_IMM(BPF_REG_8, 1), 8988 + 8989 + /* 2nd lookup from map */ 8990 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 8991 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 8992 + BPF_LD_MAP_FD(BPF_REG_1, 0), 8993 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 8994 + BPF_FUNC_map_lookup_elem), 8995 + /* write map_value_ptr_or_null into stack frame of main prog at fp-16 */ 8996 + BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), 8997 + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 8998 + BPF_MOV64_IMM(BPF_REG_9, 0), 8999 + BPF_JMP_IMM(BPF_JA, 0, 0, 1), 9000 + BPF_MOV64_IMM(BPF_REG_9, 1), 9001 + 9002 + /* call 3rd func with fp-8, 0|1, fp-16, 0|1 */ 9003 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 9004 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_8), 9005 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_7), 9006 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_9), 9007 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 9008 + BPF_EXIT_INSN(), 9009 + 9010 + /* subprog 2 */ 9011 + /* if arg2 == 1 do *arg1 = 0 */ 9012 + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 1, 2), 9013 + /* fetch map_value_ptr from the stack of this function */ 9014 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), 9015 + /* write into map value */ 9016 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 9017 + 9018 + /* if arg4 == 0 do *arg3 = 0 */ 9019 + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 0, 2), 9020 + /* fetch map_value_ptr from the stack of this function */ 9021 + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), 9022 + /* write into map value */ 9023 + BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 9024 + BPF_EXIT_INSN(), 9025 + }, 9026 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 9027 + .fixup_map1 = { 12, 22 }, 9028 + .result = REJECT, 9029 + .errstr = "R0 invalid mem access 'inv'", 9030 + }, 9031 + { 9032 + "calls: pkt_ptr spill into caller stack", 9033 + .insns = { 9034 + BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 9035 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), 9036 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 1), 9037 + BPF_EXIT_INSN(), 9038 + 9039 + /* subprog 1 */ 9040 + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 9041 + offsetof(struct __sk_buff, data)), 9042 + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 9043 + offsetof(struct __sk_buff, data_end)), 9044 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 9045 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), 9046 + /* spill unchecked pkt_ptr into stack of caller */ 9047 + BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_2, 0), 9048 + BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 2), 9049 + /* now the pkt range is verified, read pkt_ptr from stack */ 9050 + BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_4, 0), 9051 + /* write 4 bytes into packet */ 9052 + BPF_ST_MEM(BPF_W, BPF_REG_2, 0, 0), 9053 + BPF_EXIT_INSN(), 9054 + }, 9055 + .result = ACCEPT, 9056 + .prog_type = BPF_PROG_TYPE_SCHED_CLS, 8100 9057 }, 8101 9058 }; 8102 9059