1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ 3 #include <linux/bpf.h> 4 #include <linux/bpf_verifier.h> 5 #include <linux/filter.h> 6 #include <linux/sort.h> 7 8 #include "diagnostics.h" 9 10 #define verbose(env, fmt, args...) bpf_verifier_log_write(env, fmt, ##args) 11 12 /* non-recursive DFS pseudo code 13 * 1 procedure DFS-iterative(G,v): 14 * 2 label v as discovered 15 * 3 let S be a stack 16 * 4 S.push(v) 17 * 5 while S is not empty 18 * 6 t <- S.peek() 19 * 7 if t is what we're looking for: 20 * 8 return t 21 * 9 for all edges e in G.adjacentEdges(t) do 22 * 10 if edge e is already labelled 23 * 11 continue with the next edge 24 * 12 w <- G.adjacentVertex(t,e) 25 * 13 if vertex w is not discovered and not explored 26 * 14 label e as tree-edge 27 * 15 label w as discovered 28 * 16 S.push(w) 29 * 17 continue at 5 30 * 18 else if vertex w is discovered 31 * 19 label e as back-edge 32 * 20 else 33 * 21 // vertex w is explored 34 * 22 label e as forward- or cross-edge 35 * 23 label t as explored 36 * 24 S.pop() 37 * 38 * convention: 39 * 0x10 - discovered 40 * 0x11 - discovered and fall-through edge labelled 41 * 0x12 - discovered and fall-through and branch edges labelled 42 * 0x20 - explored 43 */ 44 45 enum { 46 DISCOVERED = 0x10, 47 EXPLORED = 0x20, 48 FALLTHROUGH = 1, 49 BRANCH = 2, 50 }; 51 52 static void mark_subprog_changes_pkt_data(struct bpf_verifier_env *env, int off) 53 { 54 struct bpf_subprog_info *subprog; 55 56 subprog = bpf_find_containing_subprog(env, off); 57 subprog->changes_pkt_data = true; 58 } 59 60 static void mark_subprog_might_sleep(struct bpf_verifier_env *env, int off) 61 { 62 struct bpf_subprog_info *subprog; 63 64 subprog = bpf_find_containing_subprog(env, off); 65 subprog->might_sleep = true; 66 } 67 68 static void mark_subprog_might_throw(struct bpf_verifier_env *env, int off) 69 { 70 struct bpf_subprog_info *subprog; 71 72 subprog = bpf_find_containing_subprog(env, off); 73 subprog->might_throw = true; 74 } 75 76 /* 't' is an index of a call-site. 77 * 'w' is a callee entry point. 78 * Eventually this function would be called when env->cfg.insn_state[w] == EXPLORED. 79 * Rely on DFS traversal order and absence of recursive calls to guarantee that 80 * callee's effect marks would be correct at that moment. 81 */ 82 static void merge_callee_effects(struct bpf_verifier_env *env, int t, int w) 83 { 84 struct bpf_subprog_info *caller, *callee; 85 86 caller = bpf_find_containing_subprog(env, t); 87 callee = bpf_find_containing_subprog(env, w); 88 caller->changes_pkt_data |= callee->changes_pkt_data; 89 caller->might_sleep |= callee->might_sleep; 90 caller->might_throw |= callee->might_throw; 91 } 92 93 enum { 94 DONE_EXPLORING = 0, 95 KEEP_EXPLORING = 1, 96 }; 97 98 /* t, w, e - match pseudo-code above: 99 * t - index of current instruction 100 * w - next instruction 101 * e - edge 102 */ 103 static int push_insn(int t, int w, int e, struct bpf_verifier_env *env) 104 { 105 int *insn_stack = env->cfg.insn_stack; 106 int *insn_state = env->cfg.insn_state; 107 108 if (e == FALLTHROUGH && insn_state[t] >= (DISCOVERED | FALLTHROUGH)) 109 return DONE_EXPLORING; 110 111 if (e == BRANCH && insn_state[t] >= (DISCOVERED | BRANCH)) 112 return DONE_EXPLORING; 113 114 if (w < 0 || w >= env->prog->len) { 115 verbose_linfo(env, t, "%d: ", t); 116 verbose(env, "jump out of range from insn %d to %d\n", t, w); 117 bpf_diag_program_structure( 118 env, t, "jump out of range", "Keep branch targets inside the program.", 119 "Instruction %d jumps to instruction %d, but the program only contains instructions 0 through %d.", 120 t, w, env->prog->len - 1); 121 return -EINVAL; 122 } 123 124 if (e == BRANCH) { 125 /* mark branch target for state pruning */ 126 mark_prune_point(env, w); 127 mark_jmp_point(env, w); 128 } 129 130 if (insn_state[w] == 0) { 131 /* tree-edge */ 132 insn_state[t] = DISCOVERED | e; 133 insn_state[w] = DISCOVERED; 134 if (env->cfg.cur_stack >= env->prog->len) 135 return -E2BIG; 136 insn_stack[env->cfg.cur_stack++] = w; 137 return KEEP_EXPLORING; 138 } else if ((insn_state[w] & 0xF0) == DISCOVERED) { 139 if (env->bpf_capable) 140 return DONE_EXPLORING; 141 verbose_linfo(env, t, "%d: ", t); 142 verbose_linfo(env, w, "%d: ", w); 143 verbose(env, "back-edge from insn %d to %d\n", t, w); 144 bpf_diag_program_structure( 145 env, t, "back-edge is not allowed", 146 "Load with privileges that allow this back-edge, or rewrite the control flow so it does not branch backward.", 147 "Instruction %d branches back to instruction %d. This program is being rejected without the privilege needed for this back-edge.", 148 t, w); 149 return -EINVAL; 150 } else if (insn_state[w] == EXPLORED) { 151 /* forward- or cross-edge */ 152 insn_state[t] = DISCOVERED | e; 153 } else { 154 verifier_bug(env, "insn state internal bug"); 155 return -EFAULT; 156 } 157 return DONE_EXPLORING; 158 } 159 160 static int visit_func_call_insn(int t, struct bpf_insn *insns, 161 struct bpf_verifier_env *env, 162 bool visit_callee) 163 { 164 int ret, insn_sz; 165 int w; 166 167 insn_sz = bpf_is_ldimm64(&insns[t]) ? 2 : 1; 168 ret = push_insn(t, t + insn_sz, FALLTHROUGH, env); 169 if (ret) 170 return ret; 171 172 mark_prune_point(env, t + insn_sz); 173 /* when we exit from subprog, we need to record non-linear history */ 174 mark_jmp_point(env, t + insn_sz); 175 176 if (visit_callee) { 177 w = t + insns[t].imm + 1; 178 mark_prune_point(env, t); 179 merge_callee_effects(env, t, w); 180 ret = push_insn(t, w, BRANCH, env); 181 } 182 return ret; 183 } 184 185 struct bpf_iarray *bpf_iarray_realloc(struct bpf_iarray *old, size_t n_elem) 186 { 187 size_t new_size = sizeof(struct bpf_iarray) + n_elem * sizeof(old->items[0]); 188 struct bpf_iarray *new; 189 190 new = kvrealloc(old, new_size, GFP_KERNEL_ACCOUNT); 191 if (!new) { 192 /* this is what callers always want, so simplify the call site */ 193 kvfree(old); 194 return NULL; 195 } 196 197 new->cnt = n_elem; 198 return new; 199 } 200 201 static int copy_insn_array(struct bpf_map *map, u32 start, u32 end, u32 *items) 202 { 203 struct bpf_insn_array_value *value; 204 u32 i; 205 206 for (i = start; i <= end; i++) { 207 value = map->ops->map_lookup_elem(map, &i); 208 /* 209 * map_lookup_elem of an array map will never return an error, 210 * but not checking it makes some static analysers to worry 211 */ 212 if (IS_ERR(value)) 213 return PTR_ERR(value); 214 else if (!value) 215 return -EINVAL; 216 items[i - start] = value->xlated_off; 217 } 218 return 0; 219 } 220 221 static int cmp_ptr_to_u32(const void *a, const void *b) 222 { 223 return *(u32 *)a - *(u32 *)b; 224 } 225 226 static int sort_insn_array_uniq(u32 *items, int cnt) 227 { 228 int unique = 1; 229 int i; 230 231 sort(items, cnt, sizeof(items[0]), cmp_ptr_to_u32, NULL); 232 233 for (i = 1; i < cnt; i++) 234 if (items[i] != items[unique - 1]) 235 items[unique++] = items[i]; 236 237 return unique; 238 } 239 240 /* 241 * sort_unique({map[start], ..., map[end]}) into off 242 */ 243 int bpf_copy_insn_array_uniq(struct bpf_map *map, u32 start, u32 end, u32 *off) 244 { 245 u32 n = end - start + 1; 246 int err; 247 248 err = copy_insn_array(map, start, end, off); 249 if (err) 250 return err; 251 252 return sort_insn_array_uniq(off, n); 253 } 254 255 /* 256 * Copy all unique offsets from the map 257 */ 258 static struct bpf_iarray *jt_from_map(struct bpf_map *map) 259 { 260 struct bpf_iarray *jt; 261 int err; 262 int n; 263 264 jt = bpf_iarray_realloc(NULL, map->max_entries); 265 if (!jt) 266 return ERR_PTR(-ENOMEM); 267 268 n = bpf_copy_insn_array_uniq(map, 0, map->max_entries - 1, jt->items); 269 if (n < 0) { 270 err = n; 271 goto err_free; 272 } 273 if (n == 0) { 274 err = -EINVAL; 275 goto err_free; 276 } 277 jt->cnt = n; 278 return jt; 279 280 err_free: 281 kvfree(jt); 282 return ERR_PTR(err); 283 } 284 285 /* 286 * Find and collect all maps which fit in the subprog. Return the result as one 287 * combined jump table in jt->items (allocated with kvcalloc) 288 */ 289 static struct bpf_iarray *jt_from_subprog(struct bpf_verifier_env *env, 290 int subprog_start, int subprog_end) 291 { 292 struct bpf_iarray *jt = NULL; 293 struct bpf_map *map; 294 struct bpf_iarray *jt_cur; 295 int i; 296 297 for (i = 0; i < env->insn_array_map_cnt; i++) { 298 /* 299 * TODO (when needed): collect only jump tables, not static keys 300 * or maps for indirect calls 301 */ 302 map = env->insn_array_maps[i]; 303 304 jt_cur = jt_from_map(map); 305 if (IS_ERR(jt_cur)) { 306 kvfree(jt); 307 return jt_cur; 308 } 309 310 /* 311 * This is enough to check one element. The full table is 312 * checked to fit inside the subprog later in create_jt() 313 */ 314 if (jt_cur->items[0] >= subprog_start && jt_cur->items[0] < subprog_end) { 315 u32 old_cnt = jt ? jt->cnt : 0; 316 jt = bpf_iarray_realloc(jt, old_cnt + jt_cur->cnt); 317 if (!jt) { 318 kvfree(jt_cur); 319 return ERR_PTR(-ENOMEM); 320 } 321 memcpy(jt->items + old_cnt, jt_cur->items, jt_cur->cnt << 2); 322 } 323 324 kvfree(jt_cur); 325 } 326 327 if (!jt) { 328 verbose(env, "no jump tables found for subprog starting at %u\n", subprog_start); 329 bpf_diag_program_structure( 330 env, subprog_start, "missing jump table", 331 "Make sure subprograms containing gotox instructions are accompanied by jump tables referencing these subprograms.", 332 "No jump table was found for the subprogram that starts at instruction %u.", 333 subprog_start); 334 return ERR_PTR(-EINVAL); 335 } 336 337 jt->cnt = sort_insn_array_uniq(jt->items, jt->cnt); 338 return jt; 339 } 340 341 static struct bpf_iarray * 342 create_jt(int t, struct bpf_verifier_env *env) 343 { 344 struct bpf_subprog_info *subprog; 345 int subprog_start, subprog_end; 346 struct bpf_iarray *jt; 347 int i; 348 349 subprog = bpf_find_containing_subprog(env, t); 350 subprog_start = subprog->start; 351 subprog_end = (subprog + 1)->start; 352 jt = jt_from_subprog(env, subprog_start, subprog_end); 353 if (IS_ERR(jt)) 354 return jt; 355 356 /* Check that the every element of the jump table fits within the given subprogram */ 357 for (i = 0; i < jt->cnt; i++) { 358 if (jt->items[i] < subprog_start || jt->items[i] >= subprog_end) { 359 verbose(env, "jump table for insn %d points outside of the subprog [%u,%u]\n", 360 t, subprog_start, subprog_end); 361 bpf_diag_program_structure( 362 env, t, "jump table target out of range", 363 "Keep every jump-table target inside the same subprogram.", 364 "The jump table for instruction %d points outside subprogram range [%u,%u).", 365 t, subprog_start, subprog_end); 366 kvfree(jt); 367 return ERR_PTR(-EINVAL); 368 } 369 } 370 371 return jt; 372 } 373 374 /* "conditional jump with N edges" */ 375 static int visit_gotox_insn(int t, struct bpf_verifier_env *env) 376 { 377 int *insn_stack = env->cfg.insn_stack; 378 int *insn_state = env->cfg.insn_state; 379 bool keep_exploring = false; 380 struct bpf_iarray *jt; 381 int i, w; 382 383 jt = env->insn_aux_data[t].jt; 384 if (!jt) { 385 jt = create_jt(t, env); 386 if (IS_ERR(jt)) 387 return PTR_ERR(jt); 388 389 env->insn_aux_data[t].jt = jt; 390 } 391 392 mark_prune_point(env, t); 393 for (i = 0; i < jt->cnt; i++) { 394 w = jt->items[i]; 395 if (w < 0 || w >= env->prog->len) { 396 verbose(env, "indirect jump out of range from insn %d to %d\n", t, w); 397 bpf_diag_program_structure( 398 env, t, "indirect jump out of range", 399 "Keep indirect jump targets inside the program.", 400 "Instruction %d can jump indirectly to instruction %d, but the program only contains instructions 0 through %d.", 401 t, w, env->prog->len - 1); 402 return -EINVAL; 403 } 404 405 mark_jmp_point(env, w); 406 407 /* EXPLORED || DISCOVERED */ 408 if (insn_state[w]) 409 continue; 410 411 if (env->cfg.cur_stack >= env->prog->len) 412 return -E2BIG; 413 414 insn_stack[env->cfg.cur_stack++] = w; 415 insn_state[w] |= DISCOVERED; 416 keep_exploring = true; 417 } 418 419 return keep_exploring ? KEEP_EXPLORING : DONE_EXPLORING; 420 } 421 422 /* 423 * Instructions that can abnormally return from a subprog (tail_call 424 * upon success, ld_{abs,ind} upon load failure) have a hidden exit 425 * that the verifier must account for. 426 */ 427 static int visit_abnormal_return_insn(struct bpf_verifier_env *env, int t) 428 { 429 struct bpf_subprog_info *subprog; 430 struct bpf_iarray *jt; 431 432 if (env->insn_aux_data[t].jt) 433 return 0; 434 435 jt = bpf_iarray_realloc(NULL, 2); 436 if (!jt) 437 return -ENOMEM; 438 439 subprog = bpf_find_containing_subprog(env, t); 440 jt->items[0] = t + 1; 441 jt->items[1] = subprog->exit_idx; 442 env->insn_aux_data[t].jt = jt; 443 return 0; 444 } 445 446 /* Visits the instruction at index t and returns one of the following: 447 * < 0 - an error occurred 448 * DONE_EXPLORING - the instruction was fully explored 449 * KEEP_EXPLORING - there is still work to be done before it is fully explored 450 */ 451 static int visit_insn(int t, struct bpf_verifier_env *env) 452 { 453 struct bpf_insn *insns = env->prog->insnsi, *insn = &insns[t]; 454 int ret, off, insn_sz; 455 456 if (bpf_pseudo_func(insn)) 457 return visit_func_call_insn(t, insns, env, true); 458 459 /* All non-branch instructions have a single fall-through edge. */ 460 if (BPF_CLASS(insn->code) != BPF_JMP && 461 BPF_CLASS(insn->code) != BPF_JMP32) { 462 if (BPF_CLASS(insn->code) == BPF_LD && 463 (BPF_MODE(insn->code) == BPF_ABS || 464 BPF_MODE(insn->code) == BPF_IND)) { 465 ret = visit_abnormal_return_insn(env, t); 466 if (ret) 467 return ret; 468 } 469 insn_sz = bpf_is_ldimm64(insn) ? 2 : 1; 470 return push_insn(t, t + insn_sz, FALLTHROUGH, env); 471 } 472 473 switch (BPF_OP(insn->code)) { 474 case BPF_EXIT: 475 return DONE_EXPLORING; 476 477 case BPF_CALL: 478 if (bpf_is_async_callback_calling_insn(insn)) 479 /* Mark this call insn as a prune point to trigger 480 * is_state_visited() check before call itself is 481 * processed by __check_func_call(). Otherwise new 482 * async state will be pushed for further exploration. 483 */ 484 mark_prune_point(env, t); 485 /* For functions that invoke callbacks it is not known how many times 486 * callback would be called. Verifier models callback calling functions 487 * by repeatedly visiting callback bodies and returning to origin call 488 * instruction. 489 * In order to stop such iteration verifier needs to identify when a 490 * state identical some state from a previous iteration is reached. 491 * Check below forces creation of checkpoint before callback calling 492 * instruction to allow search for such identical states. 493 */ 494 if (bpf_is_sync_callback_calling_insn(insn)) { 495 mark_calls_callback(env, t); 496 mark_force_checkpoint(env, t); 497 mark_prune_point(env, t); 498 mark_jmp_point(env, t); 499 } 500 if (bpf_helper_call(insn)) { 501 const struct bpf_func_proto *fp; 502 503 ret = bpf_get_helper_proto(env, insn->imm, &fp); 504 /* If called in a non-sleepable context program will be 505 * rejected anyway, so we should end up with precise 506 * sleepable marks on subprogs, except for dead code 507 * elimination. 508 */ 509 if (ret == 0 && fp->might_sleep) 510 mark_subprog_might_sleep(env, t); 511 if (bpf_helper_changes_pkt_data(insn->imm)) 512 mark_subprog_changes_pkt_data(env, t); 513 if (insn->imm == BPF_FUNC_tail_call) { 514 ret = visit_abnormal_return_insn(env, t); 515 if (ret) 516 return ret; 517 } 518 } else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { 519 struct bpf_call_arg_meta meta; 520 521 ret = bpf_fetch_kfunc_arg_meta(env, insn->imm, insn->off, &meta); 522 if (ret == 0 && bpf_is_iter_next_kfunc(&meta)) { 523 mark_prune_point(env, t); 524 /* Checking and saving state checkpoints at iter_next() call 525 * is crucial for fast convergence of open-coded iterator loop 526 * logic, so we need to force it. If we don't do that, 527 * is_state_visited() might skip saving a checkpoint, causing 528 * unnecessarily long sequence of not checkpointed 529 * instructions and jumps, leading to exhaustion of jump 530 * history buffer, and potentially other undesired outcomes. 531 * It is expected that with correct open-coded iterators 532 * convergence will happen quickly, so we don't run a risk of 533 * exhausting memory. 534 */ 535 mark_force_checkpoint(env, t); 536 } 537 /* Same as helpers, if called in a non-sleepable context 538 * program will be rejected anyway, so we should end up 539 * with precise sleepable marks on subprogs, except for 540 * dead code elimination. 541 */ 542 if (ret == 0 && bpf_is_kfunc_sleepable(&meta)) 543 mark_subprog_might_sleep(env, t); 544 if (ret == 0 && bpf_is_kfunc_pkt_changing(&meta)) 545 mark_subprog_changes_pkt_data(env, t); 546 if (ret == 0 && bpf_is_throw_kfunc(insn)) 547 mark_subprog_might_throw(env, t); 548 } 549 return visit_func_call_insn(t, insns, env, insn->src_reg == BPF_PSEUDO_CALL); 550 551 case BPF_JA: 552 if (BPF_SRC(insn->code) == BPF_X) 553 return visit_gotox_insn(t, env); 554 555 if (BPF_CLASS(insn->code) == BPF_JMP) 556 off = insn->off; 557 else 558 off = insn->imm; 559 560 /* unconditional jump with single edge */ 561 ret = push_insn(t, t + off + 1, FALLTHROUGH, env); 562 if (ret) 563 return ret; 564 565 mark_prune_point(env, t + off + 1); 566 mark_jmp_point(env, t + off + 1); 567 568 return ret; 569 570 default: 571 /* conditional jump with two edges */ 572 mark_prune_point(env, t); 573 if (bpf_is_may_goto_insn(insn)) 574 mark_force_checkpoint(env, t); 575 576 ret = push_insn(t, t + 1, FALLTHROUGH, env); 577 if (ret) 578 return ret; 579 580 return push_insn(t, t + insn->off + 1, BRANCH, env); 581 } 582 } 583 584 /* non-recursive depth-first-search to detect loops in BPF program 585 * loop == back-edge in directed graph 586 */ 587 int bpf_check_cfg(struct bpf_verifier_env *env) 588 { 589 int insn_cnt = env->prog->len; 590 int *insn_stack, *insn_state; 591 int ex_insn_beg, i, ret = 0; 592 593 insn_state = env->cfg.insn_state = kvzalloc_objs(int, insn_cnt, 594 GFP_KERNEL_ACCOUNT); 595 if (!insn_state) 596 return -ENOMEM; 597 598 insn_stack = env->cfg.insn_stack = kvzalloc_objs(int, insn_cnt, 599 GFP_KERNEL_ACCOUNT); 600 if (!insn_stack) { 601 kvfree(insn_state); 602 return -ENOMEM; 603 } 604 605 ex_insn_beg = env->exception_callback_subprog 606 ? env->subprog_info[env->exception_callback_subprog].start 607 : 0; 608 609 insn_state[0] = DISCOVERED; /* mark 1st insn as discovered */ 610 insn_stack[0] = 0; /* 0 is the first instruction */ 611 env->cfg.cur_stack = 1; 612 613 walk_cfg: 614 while (env->cfg.cur_stack > 0) { 615 int t = insn_stack[env->cfg.cur_stack - 1]; 616 617 ret = visit_insn(t, env); 618 switch (ret) { 619 case DONE_EXPLORING: 620 insn_state[t] = EXPLORED; 621 env->cfg.cur_stack--; 622 break; 623 case KEEP_EXPLORING: 624 break; 625 default: 626 if (ret > 0) { 627 verifier_bug(env, "visit_insn internal bug"); 628 ret = -EFAULT; 629 } 630 goto err_free; 631 } 632 } 633 634 if (env->cfg.cur_stack < 0) { 635 verifier_bug(env, "pop stack internal bug"); 636 ret = -EFAULT; 637 goto err_free; 638 } 639 640 if (ex_insn_beg && insn_state[ex_insn_beg] != EXPLORED) { 641 insn_state[ex_insn_beg] = DISCOVERED; 642 insn_stack[0] = ex_insn_beg; 643 env->cfg.cur_stack = 1; 644 goto walk_cfg; 645 } 646 647 for (i = 0; i < insn_cnt; i++) { 648 struct bpf_insn *insn = &env->prog->insnsi[i]; 649 650 if (insn_state[i] != EXPLORED) { 651 verbose(env, "unreachable insn %d\n", i); 652 bpf_diag_program_structure( 653 env, i, "unreachable instruction", 654 "Remove the unreachable instruction or add valid control flow that reaches it.", 655 "Instruction %d is not reachable from the program entry point.", i); 656 ret = -EINVAL; 657 goto err_free; 658 } 659 if (bpf_is_ldimm64(insn)) { 660 if (insn_state[i + 1] != 0) { 661 verbose(env, "jump into the middle of ldimm64 insn %d\n", i); 662 bpf_diag_program_structure( 663 env, i, "jump into ldimm64 immediate", 664 "Target the first instruction of the ldimm64 pair, or restructure the jump target.", 665 "Control flow reaches the second half of the ldimm64 instruction pair that starts at instruction %d.", 666 i); 667 ret = -EINVAL; 668 goto err_free; 669 } 670 i++; /* skip second half of ldimm64 */ 671 } 672 } 673 ret = 0; /* cfg looks good */ 674 env->prog->aux->changes_pkt_data = env->subprog_info[0].changes_pkt_data; 675 env->prog->aux->might_sleep = env->subprog_info[0].might_sleep; 676 677 err_free: 678 kvfree(insn_state); 679 kvfree(insn_stack); 680 env->cfg.insn_state = env->cfg.insn_stack = NULL; 681 return ret; 682 } 683 684 /* 685 * For each subprogram 'i' fill array env->cfg.insn_subprogram sub-range 686 * [env->subprog_info[i].postorder_start, env->subprog_info[i+1].postorder_start) 687 * with indices of 'i' instructions in postorder. 688 */ 689 int bpf_compute_postorder(struct bpf_verifier_env *env) 690 { 691 u32 cur_postorder, i, top, stack_sz, s; 692 int *stack = NULL, *postorder = NULL, *state = NULL; 693 struct bpf_iarray *succ; 694 695 postorder = kvzalloc_objs(int, env->prog->len, GFP_KERNEL_ACCOUNT); 696 state = kvzalloc_objs(int, env->prog->len, GFP_KERNEL_ACCOUNT); 697 stack = kvzalloc_objs(int, env->prog->len, GFP_KERNEL_ACCOUNT); 698 if (!postorder || !state || !stack) { 699 kvfree(postorder); 700 kvfree(state); 701 kvfree(stack); 702 return -ENOMEM; 703 } 704 cur_postorder = 0; 705 for (i = 0; i < env->subprog_cnt; i++) { 706 env->subprog_info[i].postorder_start = cur_postorder; 707 stack[0] = env->subprog_info[i].start; 708 stack_sz = 1; 709 do { 710 top = stack[stack_sz - 1]; 711 state[top] |= DISCOVERED; 712 if (state[top] & EXPLORED) { 713 postorder[cur_postorder++] = top; 714 stack_sz--; 715 continue; 716 } 717 succ = bpf_insn_successors(env, top); 718 for (s = 0; s < succ->cnt; ++s) { 719 if (!state[succ->items[s]]) { 720 stack[stack_sz++] = succ->items[s]; 721 state[succ->items[s]] |= DISCOVERED; 722 } 723 } 724 state[top] |= EXPLORED; 725 } while (stack_sz); 726 } 727 env->subprog_info[i].postorder_start = cur_postorder; 728 env->cfg.insn_postorder = postorder; 729 env->cfg.cur_postorder = cur_postorder; 730 kvfree(stack); 731 kvfree(state); 732 return 0; 733 } 734 735 /* 736 * Compute strongly connected components (SCCs) on the CFG. 737 * Assign an SCC number to each instruction, recorded in env->insn_aux[*].scc. 738 * If instruction is a sole member of its SCC and there are no self edges, 739 * assign it SCC number of zero. 740 * Uses a non-recursive adaptation of Tarjan's algorithm for SCC computation. 741 */ 742 int bpf_compute_scc(struct bpf_verifier_env *env) 743 { 744 const u32 NOT_ON_STACK = U32_MAX; 745 746 struct bpf_insn_aux_data *aux = env->insn_aux_data; 747 const u32 insn_cnt = env->prog->len; 748 int stack_sz, dfs_sz, err = 0; 749 u32 *stack, *pre, *low, *dfs; 750 u32 i, j, t, w; 751 u32 next_preorder_num; 752 u32 next_scc_id; 753 bool assign_scc; 754 struct bpf_iarray *succ; 755 756 next_preorder_num = 1; 757 next_scc_id = 1; 758 /* 759 * - 'stack' accumulates vertices in DFS order, see invariant comment below; 760 * - 'pre[t] == p' => preorder number of vertex 't' is 'p'; 761 * - 'low[t] == n' => smallest preorder number of the vertex reachable from 't' is 'n'; 762 * - 'dfs' DFS traversal stack, used to emulate explicit recursion. 763 */ 764 stack = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT); 765 pre = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT); 766 low = kvcalloc(insn_cnt, sizeof(int), GFP_KERNEL_ACCOUNT); 767 dfs = kvcalloc(insn_cnt, sizeof(*dfs), GFP_KERNEL_ACCOUNT); 768 if (!stack || !pre || !low || !dfs) { 769 err = -ENOMEM; 770 goto exit; 771 } 772 /* 773 * References: 774 * [1] R. Tarjan "Depth-First Search and Linear Graph Algorithms" 775 * [2] D. J. Pearce "A Space-Efficient Algorithm for Finding Strongly Connected Components" 776 * 777 * The algorithm maintains the following invariant: 778 * - suppose there is a path 'u' ~> 'v', such that 'pre[v] < pre[u]'; 779 * - then, vertex 'u' remains on stack while vertex 'v' is on stack. 780 * 781 * Consequently: 782 * - If 'low[v] < pre[v]', there is a path from 'v' to some vertex 'u', 783 * such that 'pre[u] == low[v]'; vertex 'u' is currently on the stack, 784 * and thus there is an SCC (loop) containing both 'u' and 'v'. 785 * - If 'low[v] == pre[v]', loops containing 'v' have been explored, 786 * and 'v' can be considered the root of some SCC. 787 * 788 * Here is a pseudo-code for an explicitly recursive version of the algorithm: 789 * 790 * NOT_ON_STACK = insn_cnt + 1 791 * pre = [0] * insn_cnt 792 * low = [0] * insn_cnt 793 * scc = [0] * insn_cnt 794 * stack = [] 795 * 796 * next_preorder_num = 1 797 * next_scc_id = 1 798 * 799 * def recur(w): 800 * nonlocal next_preorder_num 801 * nonlocal next_scc_id 802 * 803 * pre[w] = next_preorder_num 804 * low[w] = next_preorder_num 805 * next_preorder_num += 1 806 * stack.append(w) 807 * for s in successors(w): 808 * # Note: for classic algorithm the block below should look as: 809 * # 810 * # if pre[s] == 0: 811 * # recur(s) 812 * # low[w] = min(low[w], low[s]) 813 * # elif low[s] != NOT_ON_STACK: 814 * # low[w] = min(low[w], pre[s]) 815 * # 816 * # But replacing both 'min' instructions with 'low[w] = min(low[w], low[s])' 817 * # does not break the invariant and makes iterative version of the algorithm 818 * # simpler. See 'Algorithm #3' from [2]. 819 * 820 * # 's' not yet visited 821 * if pre[s] == 0: 822 * recur(s) 823 * # if 's' is on stack, pick lowest reachable preorder number from it; 824 * # if 's' is not on stack 'low[s] == NOT_ON_STACK > low[w]', 825 * # so 'min' would be a noop. 826 * low[w] = min(low[w], low[s]) 827 * 828 * if low[w] == pre[w]: 829 * # 'w' is the root of an SCC, pop all vertices 830 * # below 'w' on stack and assign same SCC to them. 831 * while True: 832 * t = stack.pop() 833 * low[t] = NOT_ON_STACK 834 * scc[t] = next_scc_id 835 * if t == w: 836 * break 837 * next_scc_id += 1 838 * 839 * for i in range(0, insn_cnt): 840 * if pre[i] == 0: 841 * recur(i) 842 * 843 * Below implementation replaces explicit recursion with array 'dfs'. 844 */ 845 for (i = 0; i < insn_cnt; i++) { 846 if (pre[i]) 847 continue; 848 stack_sz = 0; 849 dfs_sz = 1; 850 dfs[0] = i; 851 dfs_continue: 852 while (dfs_sz) { 853 w = dfs[dfs_sz - 1]; 854 if (pre[w] == 0) { 855 low[w] = next_preorder_num; 856 pre[w] = next_preorder_num; 857 next_preorder_num++; 858 stack[stack_sz++] = w; 859 } 860 /* Visit 'w' successors */ 861 succ = bpf_insn_successors(env, w); 862 for (j = 0; j < succ->cnt; ++j) { 863 if (pre[succ->items[j]]) { 864 low[w] = min(low[w], low[succ->items[j]]); 865 } else { 866 dfs[dfs_sz++] = succ->items[j]; 867 goto dfs_continue; 868 } 869 } 870 /* 871 * Preserve the invariant: if some vertex above in the stack 872 * is reachable from 'w', keep 'w' on the stack. 873 */ 874 if (low[w] < pre[w]) { 875 dfs_sz--; 876 goto dfs_continue; 877 } 878 /* 879 * Assign SCC number only if component has two or more elements, 880 * or if component has a self reference, or if instruction is a 881 * callback calling function (implicit loop). 882 */ 883 assign_scc = stack[stack_sz - 1] != w; /* two or more elements? */ 884 for (j = 0; j < succ->cnt; ++j) { /* self reference? */ 885 if (succ->items[j] == w) { 886 assign_scc = true; 887 break; 888 } 889 } 890 if (bpf_calls_callback(env, w)) /* implicit loop? */ 891 assign_scc = true; 892 /* Pop component elements from stack */ 893 do { 894 t = stack[--stack_sz]; 895 low[t] = NOT_ON_STACK; 896 if (assign_scc) 897 aux[t].scc = next_scc_id; 898 } while (t != w); 899 if (assign_scc) 900 next_scc_id++; 901 dfs_sz--; 902 } 903 } 904 env->scc_info = kvzalloc_objs(*env->scc_info, next_scc_id, 905 GFP_KERNEL_ACCOUNT); 906 if (!env->scc_info) { 907 err = -ENOMEM; 908 goto exit; 909 } 910 env->scc_cnt = next_scc_id; 911 exit: 912 kvfree(stack); 913 kvfree(pre); 914 kvfree(low); 915 kvfree(dfs); 916 return err; 917 } 918