at v3.19-rc6 733 lines 18 kB view raw
1/* 2 * Testsuite for eBPF verifier 3 * 4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 5 * 6 * 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 * License as published by the Free Software Foundation. 9 */ 10#include <stdio.h> 11#include <unistd.h> 12#include <linux/bpf.h> 13#include <errno.h> 14#include <linux/unistd.h> 15#include <string.h> 16#include <linux/filter.h> 17#include "libbpf.h" 18 19#define MAX_INSNS 512 20#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 21 22struct bpf_test { 23 const char *descr; 24 struct bpf_insn insns[MAX_INSNS]; 25 int fixup[32]; 26 const char *errstr; 27 enum { 28 ACCEPT, 29 REJECT 30 } result; 31}; 32 33static struct bpf_test tests[] = { 34 { 35 "add+sub+mul", 36 .insns = { 37 BPF_MOV64_IMM(BPF_REG_1, 1), 38 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2), 39 BPF_MOV64_IMM(BPF_REG_2, 3), 40 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2), 41 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1), 42 BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3), 43 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 44 BPF_EXIT_INSN(), 45 }, 46 .result = ACCEPT, 47 }, 48 { 49 "unreachable", 50 .insns = { 51 BPF_EXIT_INSN(), 52 BPF_EXIT_INSN(), 53 }, 54 .errstr = "unreachable", 55 .result = REJECT, 56 }, 57 { 58 "unreachable2", 59 .insns = { 60 BPF_JMP_IMM(BPF_JA, 0, 0, 1), 61 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 62 BPF_EXIT_INSN(), 63 }, 64 .errstr = "unreachable", 65 .result = REJECT, 66 }, 67 { 68 "out of range jump", 69 .insns = { 70 BPF_JMP_IMM(BPF_JA, 0, 0, 1), 71 BPF_EXIT_INSN(), 72 }, 73 .errstr = "jump out of range", 74 .result = REJECT, 75 }, 76 { 77 "out of range jump2", 78 .insns = { 79 BPF_JMP_IMM(BPF_JA, 0, 0, -2), 80 BPF_EXIT_INSN(), 81 }, 82 .errstr = "jump out of range", 83 .result = REJECT, 84 }, 85 { 86 "test1 ld_imm64", 87 .insns = { 88 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 89 BPF_LD_IMM64(BPF_REG_0, 0), 90 BPF_LD_IMM64(BPF_REG_0, 0), 91 BPF_LD_IMM64(BPF_REG_0, 1), 92 BPF_LD_IMM64(BPF_REG_0, 1), 93 BPF_MOV64_IMM(BPF_REG_0, 2), 94 BPF_EXIT_INSN(), 95 }, 96 .errstr = "invalid BPF_LD_IMM insn", 97 .result = REJECT, 98 }, 99 { 100 "test2 ld_imm64", 101 .insns = { 102 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 103 BPF_LD_IMM64(BPF_REG_0, 0), 104 BPF_LD_IMM64(BPF_REG_0, 0), 105 BPF_LD_IMM64(BPF_REG_0, 1), 106 BPF_LD_IMM64(BPF_REG_0, 1), 107 BPF_EXIT_INSN(), 108 }, 109 .errstr = "invalid BPF_LD_IMM insn", 110 .result = REJECT, 111 }, 112 { 113 "test3 ld_imm64", 114 .insns = { 115 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 116 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0), 117 BPF_LD_IMM64(BPF_REG_0, 0), 118 BPF_LD_IMM64(BPF_REG_0, 0), 119 BPF_LD_IMM64(BPF_REG_0, 1), 120 BPF_LD_IMM64(BPF_REG_0, 1), 121 BPF_EXIT_INSN(), 122 }, 123 .errstr = "invalid bpf_ld_imm64 insn", 124 .result = REJECT, 125 }, 126 { 127 "test4 ld_imm64", 128 .insns = { 129 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0), 130 BPF_EXIT_INSN(), 131 }, 132 .errstr = "invalid bpf_ld_imm64 insn", 133 .result = REJECT, 134 }, 135 { 136 "test5 ld_imm64", 137 .insns = { 138 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0), 139 }, 140 .errstr = "invalid bpf_ld_imm64 insn", 141 .result = REJECT, 142 }, 143 { 144 "no bpf_exit", 145 .insns = { 146 BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2), 147 }, 148 .errstr = "jump out of range", 149 .result = REJECT, 150 }, 151 { 152 "loop (back-edge)", 153 .insns = { 154 BPF_JMP_IMM(BPF_JA, 0, 0, -1), 155 BPF_EXIT_INSN(), 156 }, 157 .errstr = "back-edge", 158 .result = REJECT, 159 }, 160 { 161 "loop2 (back-edge)", 162 .insns = { 163 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 164 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), 165 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 166 BPF_JMP_IMM(BPF_JA, 0, 0, -4), 167 BPF_EXIT_INSN(), 168 }, 169 .errstr = "back-edge", 170 .result = REJECT, 171 }, 172 { 173 "conditional loop", 174 .insns = { 175 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 176 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), 177 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 178 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3), 179 BPF_EXIT_INSN(), 180 }, 181 .errstr = "back-edge", 182 .result = REJECT, 183 }, 184 { 185 "read uninitialized register", 186 .insns = { 187 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 188 BPF_EXIT_INSN(), 189 }, 190 .errstr = "R2 !read_ok", 191 .result = REJECT, 192 }, 193 { 194 "read invalid register", 195 .insns = { 196 BPF_MOV64_REG(BPF_REG_0, -1), 197 BPF_EXIT_INSN(), 198 }, 199 .errstr = "R15 is invalid", 200 .result = REJECT, 201 }, 202 { 203 "program doesn't init R0 before exit", 204 .insns = { 205 BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1), 206 BPF_EXIT_INSN(), 207 }, 208 .errstr = "R0 !read_ok", 209 .result = REJECT, 210 }, 211 { 212 "program doesn't init R0 before exit in all branches", 213 .insns = { 214 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 215 BPF_MOV64_IMM(BPF_REG_0, 1), 216 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2), 217 BPF_EXIT_INSN(), 218 }, 219 .errstr = "R0 !read_ok", 220 .result = REJECT, 221 }, 222 { 223 "stack out of bounds", 224 .insns = { 225 BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0), 226 BPF_EXIT_INSN(), 227 }, 228 .errstr = "invalid stack", 229 .result = REJECT, 230 }, 231 { 232 "invalid call insn1", 233 .insns = { 234 BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0), 235 BPF_EXIT_INSN(), 236 }, 237 .errstr = "BPF_CALL uses reserved", 238 .result = REJECT, 239 }, 240 { 241 "invalid call insn2", 242 .insns = { 243 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0), 244 BPF_EXIT_INSN(), 245 }, 246 .errstr = "BPF_CALL uses reserved", 247 .result = REJECT, 248 }, 249 { 250 "invalid function call", 251 .insns = { 252 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567), 253 BPF_EXIT_INSN(), 254 }, 255 .errstr = "invalid func 1234567", 256 .result = REJECT, 257 }, 258 { 259 "uninitialized stack1", 260 .insns = { 261 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 262 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 263 BPF_LD_MAP_FD(BPF_REG_1, 0), 264 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 265 BPF_EXIT_INSN(), 266 }, 267 .fixup = {2}, 268 .errstr = "invalid indirect read from stack", 269 .result = REJECT, 270 }, 271 { 272 "uninitialized stack2", 273 .insns = { 274 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 275 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8), 276 BPF_EXIT_INSN(), 277 }, 278 .errstr = "invalid read from stack", 279 .result = REJECT, 280 }, 281 { 282 "check valid spill/fill", 283 .insns = { 284 /* spill R1(ctx) into stack */ 285 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), 286 287 /* fill it back into R2 */ 288 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8), 289 290 /* should be able to access R0 = *(R2 + 8) */ 291 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), 292 BPF_EXIT_INSN(), 293 }, 294 .result = ACCEPT, 295 }, 296 { 297 "check corrupted spill/fill", 298 .insns = { 299 /* spill R1(ctx) into stack */ 300 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), 301 302 /* mess up with R1 pointer on stack */ 303 BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23), 304 305 /* fill back into R0 should fail */ 306 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 307 308 BPF_EXIT_INSN(), 309 }, 310 .errstr = "corrupted spill", 311 .result = REJECT, 312 }, 313 { 314 "invalid src register in STX", 315 .insns = { 316 BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1), 317 BPF_EXIT_INSN(), 318 }, 319 .errstr = "R15 is invalid", 320 .result = REJECT, 321 }, 322 { 323 "invalid dst register in STX", 324 .insns = { 325 BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1), 326 BPF_EXIT_INSN(), 327 }, 328 .errstr = "R14 is invalid", 329 .result = REJECT, 330 }, 331 { 332 "invalid dst register in ST", 333 .insns = { 334 BPF_ST_MEM(BPF_B, 14, -1, -1), 335 BPF_EXIT_INSN(), 336 }, 337 .errstr = "R14 is invalid", 338 .result = REJECT, 339 }, 340 { 341 "invalid src register in LDX", 342 .insns = { 343 BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0), 344 BPF_EXIT_INSN(), 345 }, 346 .errstr = "R12 is invalid", 347 .result = REJECT, 348 }, 349 { 350 "invalid dst register in LDX", 351 .insns = { 352 BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0), 353 BPF_EXIT_INSN(), 354 }, 355 .errstr = "R11 is invalid", 356 .result = REJECT, 357 }, 358 { 359 "junk insn", 360 .insns = { 361 BPF_RAW_INSN(0, 0, 0, 0, 0), 362 BPF_EXIT_INSN(), 363 }, 364 .errstr = "invalid BPF_LD_IMM", 365 .result = REJECT, 366 }, 367 { 368 "junk insn2", 369 .insns = { 370 BPF_RAW_INSN(1, 0, 0, 0, 0), 371 BPF_EXIT_INSN(), 372 }, 373 .errstr = "BPF_LDX uses reserved fields", 374 .result = REJECT, 375 }, 376 { 377 "junk insn3", 378 .insns = { 379 BPF_RAW_INSN(-1, 0, 0, 0, 0), 380 BPF_EXIT_INSN(), 381 }, 382 .errstr = "invalid BPF_ALU opcode f0", 383 .result = REJECT, 384 }, 385 { 386 "junk insn4", 387 .insns = { 388 BPF_RAW_INSN(-1, -1, -1, -1, -1), 389 BPF_EXIT_INSN(), 390 }, 391 .errstr = "invalid BPF_ALU opcode f0", 392 .result = REJECT, 393 }, 394 { 395 "junk insn5", 396 .insns = { 397 BPF_RAW_INSN(0x7f, -1, -1, -1, -1), 398 BPF_EXIT_INSN(), 399 }, 400 .errstr = "BPF_ALU uses reserved fields", 401 .result = REJECT, 402 }, 403 { 404 "misaligned read from stack", 405 .insns = { 406 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 407 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4), 408 BPF_EXIT_INSN(), 409 }, 410 .errstr = "misaligned access", 411 .result = REJECT, 412 }, 413 { 414 "invalid map_fd for function call", 415 .insns = { 416 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 417 BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10), 418 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 419 BPF_LD_MAP_FD(BPF_REG_1, 0), 420 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem), 421 BPF_EXIT_INSN(), 422 }, 423 .errstr = "fd 0 is not pointing to valid bpf_map", 424 .result = REJECT, 425 }, 426 { 427 "don't check return value before access", 428 .insns = { 429 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 430 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 431 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 432 BPF_LD_MAP_FD(BPF_REG_1, 0), 433 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 434 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 435 BPF_EXIT_INSN(), 436 }, 437 .fixup = {3}, 438 .errstr = "R0 invalid mem access 'map_value_or_null'", 439 .result = REJECT, 440 }, 441 { 442 "access memory with incorrect alignment", 443 .insns = { 444 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 445 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 446 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 447 BPF_LD_MAP_FD(BPF_REG_1, 0), 448 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 449 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 450 BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0), 451 BPF_EXIT_INSN(), 452 }, 453 .fixup = {3}, 454 .errstr = "misaligned access", 455 .result = REJECT, 456 }, 457 { 458 "sometimes access memory with incorrect alignment", 459 .insns = { 460 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 461 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 462 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 463 BPF_LD_MAP_FD(BPF_REG_1, 0), 464 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 465 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 466 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 467 BPF_EXIT_INSN(), 468 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1), 469 BPF_EXIT_INSN(), 470 }, 471 .fixup = {3}, 472 .errstr = "R0 invalid mem access", 473 .result = REJECT, 474 }, 475 { 476 "jump test 1", 477 .insns = { 478 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 479 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8), 480 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 481 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), 482 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1), 483 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1), 484 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1), 485 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2), 486 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1), 487 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3), 488 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1), 489 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4), 490 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1), 491 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5), 492 BPF_MOV64_IMM(BPF_REG_0, 0), 493 BPF_EXIT_INSN(), 494 }, 495 .result = ACCEPT, 496 }, 497 { 498 "jump test 2", 499 .insns = { 500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 501 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2), 502 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), 503 BPF_JMP_IMM(BPF_JA, 0, 0, 14), 504 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2), 505 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0), 506 BPF_JMP_IMM(BPF_JA, 0, 0, 11), 507 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2), 508 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0), 509 BPF_JMP_IMM(BPF_JA, 0, 0, 8), 510 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), 511 BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0), 512 BPF_JMP_IMM(BPF_JA, 0, 0, 5), 513 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2), 514 BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0), 515 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 516 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1), 517 BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0), 518 BPF_MOV64_IMM(BPF_REG_0, 0), 519 BPF_EXIT_INSN(), 520 }, 521 .result = ACCEPT, 522 }, 523 { 524 "jump test 3", 525 .insns = { 526 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 527 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3), 528 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), 529 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 530 BPF_JMP_IMM(BPF_JA, 0, 0, 19), 531 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3), 532 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0), 533 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 534 BPF_JMP_IMM(BPF_JA, 0, 0, 15), 535 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3), 536 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0), 537 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32), 538 BPF_JMP_IMM(BPF_JA, 0, 0, 11), 539 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3), 540 BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0), 541 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40), 542 BPF_JMP_IMM(BPF_JA, 0, 0, 7), 543 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3), 544 BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0), 545 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48), 546 BPF_JMP_IMM(BPF_JA, 0, 0, 3), 547 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0), 548 BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0), 549 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56), 550 BPF_LD_MAP_FD(BPF_REG_1, 0), 551 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem), 552 BPF_EXIT_INSN(), 553 }, 554 .fixup = {24}, 555 .result = ACCEPT, 556 }, 557 { 558 "jump test 4", 559 .insns = { 560 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 561 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 562 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 563 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 564 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 565 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 566 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 567 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 568 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 569 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 570 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 571 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 572 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 573 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 574 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 575 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 576 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 577 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 578 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 579 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 580 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 581 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 582 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 583 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 584 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 585 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 586 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 587 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 588 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 589 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 590 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 591 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 592 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 593 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 594 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 595 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 596 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 597 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 598 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 599 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 600 BPF_MOV64_IMM(BPF_REG_0, 0), 601 BPF_EXIT_INSN(), 602 }, 603 .result = ACCEPT, 604 }, 605 { 606 "jump test 5", 607 .insns = { 608 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 609 BPF_MOV64_REG(BPF_REG_3, BPF_REG_2), 610 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 611 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 612 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 613 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 614 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 615 BPF_MOV64_IMM(BPF_REG_0, 0), 616 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 617 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 618 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 619 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 620 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 621 BPF_MOV64_IMM(BPF_REG_0, 0), 622 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 623 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 624 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 625 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 626 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 627 BPF_MOV64_IMM(BPF_REG_0, 0), 628 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 629 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 630 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 631 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 632 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 633 BPF_MOV64_IMM(BPF_REG_0, 0), 634 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 635 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 636 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 637 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 638 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 639 BPF_MOV64_IMM(BPF_REG_0, 0), 640 BPF_EXIT_INSN(), 641 }, 642 .result = ACCEPT, 643 }, 644}; 645 646static int probe_filter_length(struct bpf_insn *fp) 647{ 648 int len = 0; 649 650 for (len = MAX_INSNS - 1; len > 0; --len) 651 if (fp[len].code != 0 || fp[len].imm != 0) 652 break; 653 654 return len + 1; 655} 656 657static int create_map(void) 658{ 659 long long key, value = 0; 660 int map_fd; 661 662 map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1024); 663 if (map_fd < 0) { 664 printf("failed to create map '%s'\n", strerror(errno)); 665 } 666 667 return map_fd; 668} 669 670static int test(void) 671{ 672 int prog_fd, i, pass_cnt = 0, err_cnt = 0; 673 674 for (i = 0; i < ARRAY_SIZE(tests); i++) { 675 struct bpf_insn *prog = tests[i].insns; 676 int prog_len = probe_filter_length(prog); 677 int *fixup = tests[i].fixup; 678 int map_fd = -1; 679 680 if (*fixup) { 681 map_fd = create_map(); 682 683 do { 684 prog[*fixup].imm = map_fd; 685 fixup++; 686 } while (*fixup); 687 } 688 printf("#%d %s ", i, tests[i].descr); 689 690 prog_fd = bpf_prog_load(BPF_PROG_TYPE_UNSPEC, prog, 691 prog_len * sizeof(struct bpf_insn), 692 "GPL"); 693 694 if (tests[i].result == ACCEPT) { 695 if (prog_fd < 0) { 696 printf("FAIL\nfailed to load prog '%s'\n", 697 strerror(errno)); 698 printf("%s", bpf_log_buf); 699 err_cnt++; 700 goto fail; 701 } 702 } else { 703 if (prog_fd >= 0) { 704 printf("FAIL\nunexpected success to load\n"); 705 printf("%s", bpf_log_buf); 706 err_cnt++; 707 goto fail; 708 } 709 if (strstr(bpf_log_buf, tests[i].errstr) == 0) { 710 printf("FAIL\nunexpected error message: %s", 711 bpf_log_buf); 712 err_cnt++; 713 goto fail; 714 } 715 } 716 717 pass_cnt++; 718 printf("OK\n"); 719fail: 720 if (map_fd >= 0) 721 close(map_fd); 722 close(prog_fd); 723 724 } 725 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt); 726 727 return 0; 728} 729 730int main(void) 731{ 732 return test(); 733}