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