at v4.6-rc1 1311 lines 34 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 <stddef.h> 18#include <stdbool.h> 19#include <sys/resource.h> 20#include "libbpf.h" 21 22#define MAX_INSNS 512 23#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 24 25#define MAX_FIXUPS 8 26 27struct bpf_test { 28 const char *descr; 29 struct bpf_insn insns[MAX_INSNS]; 30 int fixup[MAX_FIXUPS]; 31 int prog_array_fixup[MAX_FIXUPS]; 32 const char *errstr; 33 const char *errstr_unpriv; 34 enum { 35 UNDEF, 36 ACCEPT, 37 REJECT 38 } result, result_unpriv; 39 enum bpf_prog_type prog_type; 40}; 41 42static struct bpf_test tests[] = { 43 { 44 "add+sub+mul", 45 .insns = { 46 BPF_MOV64_IMM(BPF_REG_1, 1), 47 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 2), 48 BPF_MOV64_IMM(BPF_REG_2, 3), 49 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_2), 50 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1), 51 BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 3), 52 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 53 BPF_EXIT_INSN(), 54 }, 55 .result = ACCEPT, 56 }, 57 { 58 "unreachable", 59 .insns = { 60 BPF_EXIT_INSN(), 61 BPF_EXIT_INSN(), 62 }, 63 .errstr = "unreachable", 64 .result = REJECT, 65 }, 66 { 67 "unreachable2", 68 .insns = { 69 BPF_JMP_IMM(BPF_JA, 0, 0, 1), 70 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 71 BPF_EXIT_INSN(), 72 }, 73 .errstr = "unreachable", 74 .result = REJECT, 75 }, 76 { 77 "out of range jump", 78 .insns = { 79 BPF_JMP_IMM(BPF_JA, 0, 0, 1), 80 BPF_EXIT_INSN(), 81 }, 82 .errstr = "jump out of range", 83 .result = REJECT, 84 }, 85 { 86 "out of range jump2", 87 .insns = { 88 BPF_JMP_IMM(BPF_JA, 0, 0, -2), 89 BPF_EXIT_INSN(), 90 }, 91 .errstr = "jump out of range", 92 .result = REJECT, 93 }, 94 { 95 "test1 ld_imm64", 96 .insns = { 97 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 98 BPF_LD_IMM64(BPF_REG_0, 0), 99 BPF_LD_IMM64(BPF_REG_0, 0), 100 BPF_LD_IMM64(BPF_REG_0, 1), 101 BPF_LD_IMM64(BPF_REG_0, 1), 102 BPF_MOV64_IMM(BPF_REG_0, 2), 103 BPF_EXIT_INSN(), 104 }, 105 .errstr = "invalid BPF_LD_IMM insn", 106 .errstr_unpriv = "R1 pointer comparison", 107 .result = REJECT, 108 }, 109 { 110 "test2 ld_imm64", 111 .insns = { 112 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 113 BPF_LD_IMM64(BPF_REG_0, 0), 114 BPF_LD_IMM64(BPF_REG_0, 0), 115 BPF_LD_IMM64(BPF_REG_0, 1), 116 BPF_LD_IMM64(BPF_REG_0, 1), 117 BPF_EXIT_INSN(), 118 }, 119 .errstr = "invalid BPF_LD_IMM insn", 120 .errstr_unpriv = "R1 pointer comparison", 121 .result = REJECT, 122 }, 123 { 124 "test3 ld_imm64", 125 .insns = { 126 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 127 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0), 128 BPF_LD_IMM64(BPF_REG_0, 0), 129 BPF_LD_IMM64(BPF_REG_0, 0), 130 BPF_LD_IMM64(BPF_REG_0, 1), 131 BPF_LD_IMM64(BPF_REG_0, 1), 132 BPF_EXIT_INSN(), 133 }, 134 .errstr = "invalid bpf_ld_imm64 insn", 135 .result = REJECT, 136 }, 137 { 138 "test4 ld_imm64", 139 .insns = { 140 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0), 141 BPF_EXIT_INSN(), 142 }, 143 .errstr = "invalid bpf_ld_imm64 insn", 144 .result = REJECT, 145 }, 146 { 147 "test5 ld_imm64", 148 .insns = { 149 BPF_RAW_INSN(BPF_LD | BPF_IMM | BPF_DW, 0, 0, 0, 0), 150 }, 151 .errstr = "invalid bpf_ld_imm64 insn", 152 .result = REJECT, 153 }, 154 { 155 "no bpf_exit", 156 .insns = { 157 BPF_ALU64_REG(BPF_MOV, BPF_REG_0, BPF_REG_2), 158 }, 159 .errstr = "jump out of range", 160 .result = REJECT, 161 }, 162 { 163 "loop (back-edge)", 164 .insns = { 165 BPF_JMP_IMM(BPF_JA, 0, 0, -1), 166 BPF_EXIT_INSN(), 167 }, 168 .errstr = "back-edge", 169 .result = REJECT, 170 }, 171 { 172 "loop2 (back-edge)", 173 .insns = { 174 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 175 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), 176 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 177 BPF_JMP_IMM(BPF_JA, 0, 0, -4), 178 BPF_EXIT_INSN(), 179 }, 180 .errstr = "back-edge", 181 .result = REJECT, 182 }, 183 { 184 "conditional loop", 185 .insns = { 186 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 187 BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), 188 BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 189 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, -3), 190 BPF_EXIT_INSN(), 191 }, 192 .errstr = "back-edge", 193 .result = REJECT, 194 }, 195 { 196 "read uninitialized register", 197 .insns = { 198 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 199 BPF_EXIT_INSN(), 200 }, 201 .errstr = "R2 !read_ok", 202 .result = REJECT, 203 }, 204 { 205 "read invalid register", 206 .insns = { 207 BPF_MOV64_REG(BPF_REG_0, -1), 208 BPF_EXIT_INSN(), 209 }, 210 .errstr = "R15 is invalid", 211 .result = REJECT, 212 }, 213 { 214 "program doesn't init R0 before exit", 215 .insns = { 216 BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_1), 217 BPF_EXIT_INSN(), 218 }, 219 .errstr = "R0 !read_ok", 220 .result = REJECT, 221 }, 222 { 223 "program doesn't init R0 before exit in all branches", 224 .insns = { 225 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 226 BPF_MOV64_IMM(BPF_REG_0, 1), 227 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2), 228 BPF_EXIT_INSN(), 229 }, 230 .errstr = "R0 !read_ok", 231 .errstr_unpriv = "R1 pointer comparison", 232 .result = REJECT, 233 }, 234 { 235 "stack out of bounds", 236 .insns = { 237 BPF_ST_MEM(BPF_DW, BPF_REG_10, 8, 0), 238 BPF_EXIT_INSN(), 239 }, 240 .errstr = "invalid stack", 241 .result = REJECT, 242 }, 243 { 244 "invalid call insn1", 245 .insns = { 246 BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, 0, 0, 0, 0), 247 BPF_EXIT_INSN(), 248 }, 249 .errstr = "BPF_CALL uses reserved", 250 .result = REJECT, 251 }, 252 { 253 "invalid call insn2", 254 .insns = { 255 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 1, 0), 256 BPF_EXIT_INSN(), 257 }, 258 .errstr = "BPF_CALL uses reserved", 259 .result = REJECT, 260 }, 261 { 262 "invalid function call", 263 .insns = { 264 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 1234567), 265 BPF_EXIT_INSN(), 266 }, 267 .errstr = "invalid func 1234567", 268 .result = REJECT, 269 }, 270 { 271 "uninitialized stack1", 272 .insns = { 273 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 274 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 275 BPF_LD_MAP_FD(BPF_REG_1, 0), 276 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 277 BPF_EXIT_INSN(), 278 }, 279 .fixup = {2}, 280 .errstr = "invalid indirect read from stack", 281 .result = REJECT, 282 }, 283 { 284 "uninitialized stack2", 285 .insns = { 286 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 287 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -8), 288 BPF_EXIT_INSN(), 289 }, 290 .errstr = "invalid read from stack", 291 .result = REJECT, 292 }, 293 { 294 "check valid spill/fill", 295 .insns = { 296 /* spill R1(ctx) into stack */ 297 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), 298 299 /* fill it back into R2 */ 300 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8), 301 302 /* should be able to access R0 = *(R2 + 8) */ 303 /* BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8), */ 304 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 305 BPF_EXIT_INSN(), 306 }, 307 .errstr_unpriv = "R0 leaks addr", 308 .result = ACCEPT, 309 .result_unpriv = REJECT, 310 }, 311 { 312 "check corrupted spill/fill", 313 .insns = { 314 /* spill R1(ctx) into stack */ 315 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), 316 317 /* mess up with R1 pointer on stack */ 318 BPF_ST_MEM(BPF_B, BPF_REG_10, -7, 0x23), 319 320 /* fill back into R0 should fail */ 321 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), 322 323 BPF_EXIT_INSN(), 324 }, 325 .errstr_unpriv = "attempt to corrupt spilled", 326 .errstr = "corrupted spill", 327 .result = REJECT, 328 }, 329 { 330 "invalid src register in STX", 331 .insns = { 332 BPF_STX_MEM(BPF_B, BPF_REG_10, -1, -1), 333 BPF_EXIT_INSN(), 334 }, 335 .errstr = "R15 is invalid", 336 .result = REJECT, 337 }, 338 { 339 "invalid dst register in STX", 340 .insns = { 341 BPF_STX_MEM(BPF_B, 14, BPF_REG_10, -1), 342 BPF_EXIT_INSN(), 343 }, 344 .errstr = "R14 is invalid", 345 .result = REJECT, 346 }, 347 { 348 "invalid dst register in ST", 349 .insns = { 350 BPF_ST_MEM(BPF_B, 14, -1, -1), 351 BPF_EXIT_INSN(), 352 }, 353 .errstr = "R14 is invalid", 354 .result = REJECT, 355 }, 356 { 357 "invalid src register in LDX", 358 .insns = { 359 BPF_LDX_MEM(BPF_B, BPF_REG_0, 12, 0), 360 BPF_EXIT_INSN(), 361 }, 362 .errstr = "R12 is invalid", 363 .result = REJECT, 364 }, 365 { 366 "invalid dst register in LDX", 367 .insns = { 368 BPF_LDX_MEM(BPF_B, 11, BPF_REG_1, 0), 369 BPF_EXIT_INSN(), 370 }, 371 .errstr = "R11 is invalid", 372 .result = REJECT, 373 }, 374 { 375 "junk insn", 376 .insns = { 377 BPF_RAW_INSN(0, 0, 0, 0, 0), 378 BPF_EXIT_INSN(), 379 }, 380 .errstr = "invalid BPF_LD_IMM", 381 .result = REJECT, 382 }, 383 { 384 "junk insn2", 385 .insns = { 386 BPF_RAW_INSN(1, 0, 0, 0, 0), 387 BPF_EXIT_INSN(), 388 }, 389 .errstr = "BPF_LDX uses reserved fields", 390 .result = REJECT, 391 }, 392 { 393 "junk insn3", 394 .insns = { 395 BPF_RAW_INSN(-1, 0, 0, 0, 0), 396 BPF_EXIT_INSN(), 397 }, 398 .errstr = "invalid BPF_ALU opcode f0", 399 .result = REJECT, 400 }, 401 { 402 "junk insn4", 403 .insns = { 404 BPF_RAW_INSN(-1, -1, -1, -1, -1), 405 BPF_EXIT_INSN(), 406 }, 407 .errstr = "invalid BPF_ALU opcode f0", 408 .result = REJECT, 409 }, 410 { 411 "junk insn5", 412 .insns = { 413 BPF_RAW_INSN(0x7f, -1, -1, -1, -1), 414 BPF_EXIT_INSN(), 415 }, 416 .errstr = "BPF_ALU uses reserved fields", 417 .result = REJECT, 418 }, 419 { 420 "misaligned read from stack", 421 .insns = { 422 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 423 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, -4), 424 BPF_EXIT_INSN(), 425 }, 426 .errstr = "misaligned access", 427 .result = REJECT, 428 }, 429 { 430 "invalid map_fd for function call", 431 .insns = { 432 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 433 BPF_ALU64_REG(BPF_MOV, BPF_REG_2, BPF_REG_10), 434 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 435 BPF_LD_MAP_FD(BPF_REG_1, 0), 436 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem), 437 BPF_EXIT_INSN(), 438 }, 439 .errstr = "fd 0 is not pointing to valid bpf_map", 440 .result = REJECT, 441 }, 442 { 443 "don't check return value before access", 444 .insns = { 445 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 446 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 447 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 448 BPF_LD_MAP_FD(BPF_REG_1, 0), 449 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 450 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 451 BPF_EXIT_INSN(), 452 }, 453 .fixup = {3}, 454 .errstr = "R0 invalid mem access 'map_value_or_null'", 455 .result = REJECT, 456 }, 457 { 458 "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, 1), 466 BPF_ST_MEM(BPF_DW, BPF_REG_0, 4, 0), 467 BPF_EXIT_INSN(), 468 }, 469 .fixup = {3}, 470 .errstr = "misaligned access", 471 .result = REJECT, 472 }, 473 { 474 "sometimes access memory with incorrect alignment", 475 .insns = { 476 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 477 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 478 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 479 BPF_LD_MAP_FD(BPF_REG_1, 0), 480 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 481 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 482 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 0), 483 BPF_EXIT_INSN(), 484 BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 1), 485 BPF_EXIT_INSN(), 486 }, 487 .fixup = {3}, 488 .errstr = "R0 invalid mem access", 489 .errstr_unpriv = "R0 leaks addr", 490 .result = REJECT, 491 }, 492 { 493 "jump test 1", 494 .insns = { 495 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 496 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -8), 497 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 498 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), 499 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1), 500 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 1), 501 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 1), 502 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 2), 503 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 1), 504 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 3), 505 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1), 506 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 4), 507 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1), 508 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 5), 509 BPF_MOV64_IMM(BPF_REG_0, 0), 510 BPF_EXIT_INSN(), 511 }, 512 .errstr_unpriv = "R1 pointer comparison", 513 .result_unpriv = REJECT, 514 .result = ACCEPT, 515 }, 516 { 517 "jump test 2", 518 .insns = { 519 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 520 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 2), 521 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), 522 BPF_JMP_IMM(BPF_JA, 0, 0, 14), 523 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 2), 524 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0), 525 BPF_JMP_IMM(BPF_JA, 0, 0, 11), 526 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 2), 527 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0), 528 BPF_JMP_IMM(BPF_JA, 0, 0, 8), 529 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), 530 BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0), 531 BPF_JMP_IMM(BPF_JA, 0, 0, 5), 532 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 2), 533 BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0), 534 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 535 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 1), 536 BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0), 537 BPF_MOV64_IMM(BPF_REG_0, 0), 538 BPF_EXIT_INSN(), 539 }, 540 .errstr_unpriv = "R1 pointer comparison", 541 .result_unpriv = REJECT, 542 .result = ACCEPT, 543 }, 544 { 545 "jump test 3", 546 .insns = { 547 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 548 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3), 549 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), 550 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 551 BPF_JMP_IMM(BPF_JA, 0, 0, 19), 552 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 3), 553 BPF_ST_MEM(BPF_DW, BPF_REG_2, -16, 0), 554 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), 555 BPF_JMP_IMM(BPF_JA, 0, 0, 15), 556 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 2, 3), 557 BPF_ST_MEM(BPF_DW, BPF_REG_2, -32, 0), 558 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -32), 559 BPF_JMP_IMM(BPF_JA, 0, 0, 11), 560 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 3), 561 BPF_ST_MEM(BPF_DW, BPF_REG_2, -40, 0), 562 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -40), 563 BPF_JMP_IMM(BPF_JA, 0, 0, 7), 564 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 3), 565 BPF_ST_MEM(BPF_DW, BPF_REG_2, -48, 0), 566 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -48), 567 BPF_JMP_IMM(BPF_JA, 0, 0, 3), 568 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 5, 0), 569 BPF_ST_MEM(BPF_DW, BPF_REG_2, -56, 0), 570 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -56), 571 BPF_LD_MAP_FD(BPF_REG_1, 0), 572 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_delete_elem), 573 BPF_EXIT_INSN(), 574 }, 575 .fixup = {24}, 576 .errstr_unpriv = "R1 pointer comparison", 577 .result_unpriv = REJECT, 578 .result = ACCEPT, 579 }, 580 { 581 "jump test 4", 582 .insns = { 583 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 584 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 585 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 586 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 587 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 588 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 589 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 590 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 591 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 592 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 593 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 594 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 595 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 596 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 597 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 598 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 599 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 600 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 601 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 602 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 603 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 604 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 605 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 606 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 607 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 608 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 609 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 610 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 611 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 612 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 613 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 614 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 615 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 1), 616 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 2), 617 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 3), 618 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 4), 619 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 620 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 621 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 622 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 623 BPF_MOV64_IMM(BPF_REG_0, 0), 624 BPF_EXIT_INSN(), 625 }, 626 .errstr_unpriv = "R1 pointer comparison", 627 .result_unpriv = REJECT, 628 .result = ACCEPT, 629 }, 630 { 631 "jump test 5", 632 .insns = { 633 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 634 BPF_MOV64_REG(BPF_REG_3, BPF_REG_2), 635 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 636 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 637 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 638 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 639 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 640 BPF_MOV64_IMM(BPF_REG_0, 0), 641 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 642 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 643 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 644 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 645 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 646 BPF_MOV64_IMM(BPF_REG_0, 0), 647 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 648 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 649 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 650 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 651 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 652 BPF_MOV64_IMM(BPF_REG_0, 0), 653 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 654 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 655 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 656 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 657 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 658 BPF_MOV64_IMM(BPF_REG_0, 0), 659 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 660 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, -8), 661 BPF_JMP_IMM(BPF_JA, 0, 0, 2), 662 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_2, -8), 663 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 664 BPF_MOV64_IMM(BPF_REG_0, 0), 665 BPF_EXIT_INSN(), 666 }, 667 .errstr_unpriv = "R1 pointer comparison", 668 .result_unpriv = REJECT, 669 .result = ACCEPT, 670 }, 671 { 672 "access skb fields ok", 673 .insns = { 674 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 675 offsetof(struct __sk_buff, len)), 676 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1), 677 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 678 offsetof(struct __sk_buff, mark)), 679 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1), 680 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 681 offsetof(struct __sk_buff, pkt_type)), 682 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1), 683 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 684 offsetof(struct __sk_buff, queue_mapping)), 685 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0), 686 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 687 offsetof(struct __sk_buff, protocol)), 688 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0), 689 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 690 offsetof(struct __sk_buff, vlan_present)), 691 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0), 692 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 693 offsetof(struct __sk_buff, vlan_tci)), 694 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0), 695 BPF_EXIT_INSN(), 696 }, 697 .result = ACCEPT, 698 }, 699 { 700 "access skb fields bad1", 701 .insns = { 702 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -4), 703 BPF_EXIT_INSN(), 704 }, 705 .errstr = "invalid bpf_context access", 706 .result = REJECT, 707 }, 708 { 709 "access skb fields bad2", 710 .insns = { 711 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 9), 712 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 713 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 714 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 715 BPF_LD_MAP_FD(BPF_REG_1, 0), 716 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 717 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 718 BPF_EXIT_INSN(), 719 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 720 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 721 offsetof(struct __sk_buff, pkt_type)), 722 BPF_EXIT_INSN(), 723 }, 724 .fixup = {4}, 725 .errstr = "different pointers", 726 .errstr_unpriv = "R1 pointer comparison", 727 .result = REJECT, 728 }, 729 { 730 "access skb fields bad3", 731 .insns = { 732 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2), 733 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 734 offsetof(struct __sk_buff, pkt_type)), 735 BPF_EXIT_INSN(), 736 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 737 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 738 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 739 BPF_LD_MAP_FD(BPF_REG_1, 0), 740 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 741 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 742 BPF_EXIT_INSN(), 743 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 744 BPF_JMP_IMM(BPF_JA, 0, 0, -12), 745 }, 746 .fixup = {6}, 747 .errstr = "different pointers", 748 .errstr_unpriv = "R1 pointer comparison", 749 .result = REJECT, 750 }, 751 { 752 "access skb fields bad4", 753 .insns = { 754 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 3), 755 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 756 offsetof(struct __sk_buff, len)), 757 BPF_MOV64_IMM(BPF_REG_0, 0), 758 BPF_EXIT_INSN(), 759 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 760 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 761 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 762 BPF_LD_MAP_FD(BPF_REG_1, 0), 763 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 764 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 765 BPF_EXIT_INSN(), 766 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 767 BPF_JMP_IMM(BPF_JA, 0, 0, -13), 768 }, 769 .fixup = {7}, 770 .errstr = "different pointers", 771 .errstr_unpriv = "R1 pointer comparison", 772 .result = REJECT, 773 }, 774 { 775 "check skb->mark is not writeable by sockets", 776 .insns = { 777 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 778 offsetof(struct __sk_buff, mark)), 779 BPF_EXIT_INSN(), 780 }, 781 .errstr = "invalid bpf_context access", 782 .errstr_unpriv = "R1 leaks addr", 783 .result = REJECT, 784 }, 785 { 786 "check skb->tc_index is not writeable by sockets", 787 .insns = { 788 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 789 offsetof(struct __sk_buff, tc_index)), 790 BPF_EXIT_INSN(), 791 }, 792 .errstr = "invalid bpf_context access", 793 .errstr_unpriv = "R1 leaks addr", 794 .result = REJECT, 795 }, 796 { 797 "check non-u32 access to cb", 798 .insns = { 799 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_1, 800 offsetof(struct __sk_buff, cb[0])), 801 BPF_EXIT_INSN(), 802 }, 803 .errstr = "invalid bpf_context access", 804 .errstr_unpriv = "R1 leaks addr", 805 .result = REJECT, 806 }, 807 { 808 "check out of range skb->cb access", 809 .insns = { 810 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 811 offsetof(struct __sk_buff, cb[0]) + 256), 812 BPF_EXIT_INSN(), 813 }, 814 .errstr = "invalid bpf_context access", 815 .errstr_unpriv = "", 816 .result = REJECT, 817 .prog_type = BPF_PROG_TYPE_SCHED_ACT, 818 }, 819 { 820 "write skb fields from socket prog", 821 .insns = { 822 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 823 offsetof(struct __sk_buff, cb[4])), 824 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1), 825 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 826 offsetof(struct __sk_buff, mark)), 827 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 828 offsetof(struct __sk_buff, tc_index)), 829 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1), 830 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 831 offsetof(struct __sk_buff, cb[0])), 832 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 833 offsetof(struct __sk_buff, cb[2])), 834 BPF_EXIT_INSN(), 835 }, 836 .result = ACCEPT, 837 .errstr_unpriv = "R1 leaks addr", 838 .result_unpriv = REJECT, 839 }, 840 { 841 "write skb fields from tc_cls_act prog", 842 .insns = { 843 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 844 offsetof(struct __sk_buff, cb[0])), 845 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 846 offsetof(struct __sk_buff, mark)), 847 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 848 offsetof(struct __sk_buff, tc_index)), 849 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 850 offsetof(struct __sk_buff, tc_index)), 851 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 852 offsetof(struct __sk_buff, cb[3])), 853 BPF_EXIT_INSN(), 854 }, 855 .errstr_unpriv = "", 856 .result_unpriv = REJECT, 857 .result = ACCEPT, 858 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 859 }, 860 { 861 "PTR_TO_STACK store/load", 862 .insns = { 863 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 864 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10), 865 BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c), 866 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2), 867 BPF_EXIT_INSN(), 868 }, 869 .result = ACCEPT, 870 }, 871 { 872 "PTR_TO_STACK store/load - bad alignment on off", 873 .insns = { 874 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 875 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 876 BPF_ST_MEM(BPF_DW, BPF_REG_1, 2, 0xfaceb00c), 877 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 2), 878 BPF_EXIT_INSN(), 879 }, 880 .result = REJECT, 881 .errstr = "misaligned access off -6 size 8", 882 }, 883 { 884 "PTR_TO_STACK store/load - bad alignment on reg", 885 .insns = { 886 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 887 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -10), 888 BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c), 889 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8), 890 BPF_EXIT_INSN(), 891 }, 892 .result = REJECT, 893 .errstr = "misaligned access off -2 size 8", 894 }, 895 { 896 "PTR_TO_STACK store/load - out of bounds low", 897 .insns = { 898 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 899 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -80000), 900 BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c), 901 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8), 902 BPF_EXIT_INSN(), 903 }, 904 .result = REJECT, 905 .errstr = "invalid stack off=-79992 size=8", 906 }, 907 { 908 "PTR_TO_STACK store/load - out of bounds high", 909 .insns = { 910 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 911 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 912 BPF_ST_MEM(BPF_DW, BPF_REG_1, 8, 0xfaceb00c), 913 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 8), 914 BPF_EXIT_INSN(), 915 }, 916 .result = REJECT, 917 .errstr = "invalid stack off=0 size=8", 918 }, 919 { 920 "unpriv: return pointer", 921 .insns = { 922 BPF_MOV64_REG(BPF_REG_0, BPF_REG_10), 923 BPF_EXIT_INSN(), 924 }, 925 .result = ACCEPT, 926 .result_unpriv = REJECT, 927 .errstr_unpriv = "R0 leaks addr", 928 }, 929 { 930 "unpriv: add const to pointer", 931 .insns = { 932 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), 933 BPF_MOV64_IMM(BPF_REG_0, 0), 934 BPF_EXIT_INSN(), 935 }, 936 .result = ACCEPT, 937 .result_unpriv = REJECT, 938 .errstr_unpriv = "R1 pointer arithmetic", 939 }, 940 { 941 "unpriv: add pointer to pointer", 942 .insns = { 943 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_10), 944 BPF_MOV64_IMM(BPF_REG_0, 0), 945 BPF_EXIT_INSN(), 946 }, 947 .result = ACCEPT, 948 .result_unpriv = REJECT, 949 .errstr_unpriv = "R1 pointer arithmetic", 950 }, 951 { 952 "unpriv: neg pointer", 953 .insns = { 954 BPF_ALU64_IMM(BPF_NEG, BPF_REG_1, 0), 955 BPF_MOV64_IMM(BPF_REG_0, 0), 956 BPF_EXIT_INSN(), 957 }, 958 .result = ACCEPT, 959 .result_unpriv = REJECT, 960 .errstr_unpriv = "R1 pointer arithmetic", 961 }, 962 { 963 "unpriv: cmp pointer with const", 964 .insns = { 965 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0), 966 BPF_MOV64_IMM(BPF_REG_0, 0), 967 BPF_EXIT_INSN(), 968 }, 969 .result = ACCEPT, 970 .result_unpriv = REJECT, 971 .errstr_unpriv = "R1 pointer comparison", 972 }, 973 { 974 "unpriv: cmp pointer with pointer", 975 .insns = { 976 BPF_JMP_REG(BPF_JEQ, BPF_REG_1, BPF_REG_10, 0), 977 BPF_MOV64_IMM(BPF_REG_0, 0), 978 BPF_EXIT_INSN(), 979 }, 980 .result = ACCEPT, 981 .result_unpriv = REJECT, 982 .errstr_unpriv = "R10 pointer comparison", 983 }, 984 { 985 "unpriv: check that printk is disallowed", 986 .insns = { 987 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 988 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 989 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), 990 BPF_MOV64_IMM(BPF_REG_2, 8), 991 BPF_MOV64_REG(BPF_REG_3, BPF_REG_1), 992 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_trace_printk), 993 BPF_MOV64_IMM(BPF_REG_0, 0), 994 BPF_EXIT_INSN(), 995 }, 996 .errstr_unpriv = "unknown func 6", 997 .result_unpriv = REJECT, 998 .result = ACCEPT, 999 }, 1000 { 1001 "unpriv: pass pointer to helper function", 1002 .insns = { 1003 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 1004 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 1005 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 1006 BPF_LD_MAP_FD(BPF_REG_1, 0), 1007 BPF_MOV64_REG(BPF_REG_3, BPF_REG_2), 1008 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2), 1009 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_update_elem), 1010 BPF_MOV64_IMM(BPF_REG_0, 0), 1011 BPF_EXIT_INSN(), 1012 }, 1013 .fixup = {3}, 1014 .errstr_unpriv = "R4 leaks addr", 1015 .result_unpriv = REJECT, 1016 .result = ACCEPT, 1017 }, 1018 { 1019 "unpriv: indirectly pass pointer on stack to helper function", 1020 .insns = { 1021 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8), 1022 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 1023 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 1024 BPF_LD_MAP_FD(BPF_REG_1, 0), 1025 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 1026 BPF_MOV64_IMM(BPF_REG_0, 0), 1027 BPF_EXIT_INSN(), 1028 }, 1029 .fixup = {3}, 1030 .errstr = "invalid indirect read from stack off -8+0 size 8", 1031 .result = REJECT, 1032 }, 1033 { 1034 "unpriv: mangle pointer on stack 1", 1035 .insns = { 1036 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8), 1037 BPF_ST_MEM(BPF_W, BPF_REG_10, -8, 0), 1038 BPF_MOV64_IMM(BPF_REG_0, 0), 1039 BPF_EXIT_INSN(), 1040 }, 1041 .errstr_unpriv = "attempt to corrupt spilled", 1042 .result_unpriv = REJECT, 1043 .result = ACCEPT, 1044 }, 1045 { 1046 "unpriv: mangle pointer on stack 2", 1047 .insns = { 1048 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8), 1049 BPF_ST_MEM(BPF_B, BPF_REG_10, -1, 0), 1050 BPF_MOV64_IMM(BPF_REG_0, 0), 1051 BPF_EXIT_INSN(), 1052 }, 1053 .errstr_unpriv = "attempt to corrupt spilled", 1054 .result_unpriv = REJECT, 1055 .result = ACCEPT, 1056 }, 1057 { 1058 "unpriv: read pointer from stack in small chunks", 1059 .insns = { 1060 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_10, -8), 1061 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8), 1062 BPF_MOV64_IMM(BPF_REG_0, 0), 1063 BPF_EXIT_INSN(), 1064 }, 1065 .errstr = "invalid size", 1066 .result = REJECT, 1067 }, 1068 { 1069 "unpriv: write pointer into ctx", 1070 .insns = { 1071 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, 0), 1072 BPF_MOV64_IMM(BPF_REG_0, 0), 1073 BPF_EXIT_INSN(), 1074 }, 1075 .errstr_unpriv = "R1 leaks addr", 1076 .result_unpriv = REJECT, 1077 .errstr = "invalid bpf_context access", 1078 .result = REJECT, 1079 }, 1080 { 1081 "unpriv: write pointer into map elem value", 1082 .insns = { 1083 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 1084 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 1085 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 1086 BPF_LD_MAP_FD(BPF_REG_1, 0), 1087 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 1088 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 1089 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 1090 BPF_EXIT_INSN(), 1091 }, 1092 .fixup = {3}, 1093 .errstr_unpriv = "R0 leaks addr", 1094 .result_unpriv = REJECT, 1095 .result = ACCEPT, 1096 }, 1097 { 1098 "unpriv: partial copy of pointer", 1099 .insns = { 1100 BPF_MOV32_REG(BPF_REG_1, BPF_REG_10), 1101 BPF_MOV64_IMM(BPF_REG_0, 0), 1102 BPF_EXIT_INSN(), 1103 }, 1104 .errstr_unpriv = "R10 partial copy", 1105 .result_unpriv = REJECT, 1106 .result = ACCEPT, 1107 }, 1108 { 1109 "unpriv: pass pointer to tail_call", 1110 .insns = { 1111 BPF_MOV64_REG(BPF_REG_3, BPF_REG_1), 1112 BPF_LD_MAP_FD(BPF_REG_2, 0), 1113 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), 1114 BPF_MOV64_IMM(BPF_REG_0, 0), 1115 BPF_EXIT_INSN(), 1116 }, 1117 .prog_array_fixup = {1}, 1118 .errstr_unpriv = "R3 leaks addr into helper", 1119 .result_unpriv = REJECT, 1120 .result = ACCEPT, 1121 }, 1122 { 1123 "unpriv: cmp map pointer with zero", 1124 .insns = { 1125 BPF_MOV64_IMM(BPF_REG_1, 0), 1126 BPF_LD_MAP_FD(BPF_REG_1, 0), 1127 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0), 1128 BPF_MOV64_IMM(BPF_REG_0, 0), 1129 BPF_EXIT_INSN(), 1130 }, 1131 .fixup = {1}, 1132 .errstr_unpriv = "R1 pointer comparison", 1133 .result_unpriv = REJECT, 1134 .result = ACCEPT, 1135 }, 1136 { 1137 "unpriv: write into frame pointer", 1138 .insns = { 1139 BPF_MOV64_REG(BPF_REG_10, BPF_REG_1), 1140 BPF_MOV64_IMM(BPF_REG_0, 0), 1141 BPF_EXIT_INSN(), 1142 }, 1143 .errstr = "frame pointer is read only", 1144 .result = REJECT, 1145 }, 1146 { 1147 "unpriv: cmp of frame pointer", 1148 .insns = { 1149 BPF_JMP_IMM(BPF_JEQ, BPF_REG_10, 0, 0), 1150 BPF_MOV64_IMM(BPF_REG_0, 0), 1151 BPF_EXIT_INSN(), 1152 }, 1153 .errstr_unpriv = "R10 pointer comparison", 1154 .result_unpriv = REJECT, 1155 .result = ACCEPT, 1156 }, 1157 { 1158 "unpriv: cmp of stack pointer", 1159 .insns = { 1160 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 1161 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 1162 BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 0), 1163 BPF_MOV64_IMM(BPF_REG_0, 0), 1164 BPF_EXIT_INSN(), 1165 }, 1166 .errstr_unpriv = "R2 pointer comparison", 1167 .result_unpriv = REJECT, 1168 .result = ACCEPT, 1169 }, 1170 { 1171 "unpriv: obfuscate stack pointer", 1172 .insns = { 1173 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 1174 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 1175 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 1176 BPF_MOV64_IMM(BPF_REG_0, 0), 1177 BPF_EXIT_INSN(), 1178 }, 1179 .errstr_unpriv = "R2 pointer arithmetic", 1180 .result_unpriv = REJECT, 1181 .result = ACCEPT, 1182 }, 1183}; 1184 1185static int probe_filter_length(struct bpf_insn *fp) 1186{ 1187 int len = 0; 1188 1189 for (len = MAX_INSNS - 1; len > 0; --len) 1190 if (fp[len].code != 0 || fp[len].imm != 0) 1191 break; 1192 1193 return len + 1; 1194} 1195 1196static int create_map(void) 1197{ 1198 int map_fd; 1199 1200 map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, 1201 sizeof(long long), sizeof(long long), 1024, 0); 1202 if (map_fd < 0) 1203 printf("failed to create map '%s'\n", strerror(errno)); 1204 1205 return map_fd; 1206} 1207 1208static int create_prog_array(void) 1209{ 1210 int map_fd; 1211 1212 map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, 1213 sizeof(int), sizeof(int), 4, 0); 1214 if (map_fd < 0) 1215 printf("failed to create prog_array '%s'\n", strerror(errno)); 1216 1217 return map_fd; 1218} 1219 1220static int test(void) 1221{ 1222 int prog_fd, i, pass_cnt = 0, err_cnt = 0; 1223 bool unpriv = geteuid() != 0; 1224 1225 for (i = 0; i < ARRAY_SIZE(tests); i++) { 1226 struct bpf_insn *prog = tests[i].insns; 1227 int prog_type = tests[i].prog_type; 1228 int prog_len = probe_filter_length(prog); 1229 int *fixup = tests[i].fixup; 1230 int *prog_array_fixup = tests[i].prog_array_fixup; 1231 int expected_result; 1232 const char *expected_errstr; 1233 int map_fd = -1, prog_array_fd = -1; 1234 1235 if (*fixup) { 1236 map_fd = create_map(); 1237 1238 do { 1239 prog[*fixup].imm = map_fd; 1240 fixup++; 1241 } while (*fixup); 1242 } 1243 if (*prog_array_fixup) { 1244 prog_array_fd = create_prog_array(); 1245 1246 do { 1247 prog[*prog_array_fixup].imm = prog_array_fd; 1248 prog_array_fixup++; 1249 } while (*prog_array_fixup); 1250 } 1251 printf("#%d %s ", i, tests[i].descr); 1252 1253 prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER, 1254 prog, prog_len * sizeof(struct bpf_insn), 1255 "GPL", 0); 1256 1257 if (unpriv && tests[i].result_unpriv != UNDEF) 1258 expected_result = tests[i].result_unpriv; 1259 else 1260 expected_result = tests[i].result; 1261 1262 if (unpriv && tests[i].errstr_unpriv) 1263 expected_errstr = tests[i].errstr_unpriv; 1264 else 1265 expected_errstr = tests[i].errstr; 1266 1267 if (expected_result == ACCEPT) { 1268 if (prog_fd < 0) { 1269 printf("FAIL\nfailed to load prog '%s'\n", 1270 strerror(errno)); 1271 printf("%s", bpf_log_buf); 1272 err_cnt++; 1273 goto fail; 1274 } 1275 } else { 1276 if (prog_fd >= 0) { 1277 printf("FAIL\nunexpected success to load\n"); 1278 printf("%s", bpf_log_buf); 1279 err_cnt++; 1280 goto fail; 1281 } 1282 if (strstr(bpf_log_buf, expected_errstr) == 0) { 1283 printf("FAIL\nunexpected error message: %s", 1284 bpf_log_buf); 1285 err_cnt++; 1286 goto fail; 1287 } 1288 } 1289 1290 pass_cnt++; 1291 printf("OK\n"); 1292fail: 1293 if (map_fd >= 0) 1294 close(map_fd); 1295 if (prog_array_fd >= 0) 1296 close(prog_array_fd); 1297 close(prog_fd); 1298 1299 } 1300 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, err_cnt); 1301 1302 return 0; 1303} 1304 1305int main(void) 1306{ 1307 struct rlimit r = {1 << 20, 1 << 20}; 1308 1309 setrlimit(RLIMIT_MEMLOCK, &r); 1310 return test(); 1311}