1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3 4 #include <linux/bpf_verifier.h> 5 #include <linux/hashtable.h> 6 #include <linux/jhash.h> 7 #include <linux/slab.h> 8 9 /* 10 * This file implements live stack slots analysis. After accumulating 11 * stack usage data, the analysis answers queries about whether a 12 * particular stack slot may be read by an instruction or any of it's 13 * successors. This data is consumed by the verifier states caching 14 * mechanism to decide which stack slots are important when looking for a 15 * visited state corresponding to the current state. 16 * 17 * The analysis is call chain sensitive, meaning that data is collected 18 * and queried for tuples (call chain, subprogram instruction index). 19 * Such sensitivity allows identifying if some subprogram call always 20 * leads to writes in the caller's stack. 21 * 22 * The basic idea is as follows: 23 * - As the verifier accumulates a set of visited states, the analysis instance 24 * accumulates a conservative estimate of stack slots that can be read 25 * or must be written for each visited tuple (call chain, instruction index). 26 * - If several states happen to visit the same instruction with the same 27 * call chain, stack usage information for the corresponding tuple is joined: 28 * - "may_read" set represents a union of all possibly read slots 29 * (any slot in "may_read" set might be read at or after the instruction); 30 * - "must_write" set represents an intersection of all possibly written slots 31 * (any slot in "must_write" set is guaranteed to be written by the instruction). 32 * - The analysis is split into two phases: 33 * - read and write marks accumulation; 34 * - read and write marks propagation. 35 * - The propagation phase is a textbook live variable data flow analysis: 36 * 37 * state[cc, i].live_after = U [state[cc, s].live_before for s in bpf_insn_successors(i)] 38 * state[cc, i].live_before = 39 * (state[cc, i].live_after / state[cc, i].must_write) U state[i].may_read 40 * 41 * Where: 42 * - `U` stands for set union 43 * - `/` stands for set difference; 44 * - `cc` stands for a call chain; 45 * - `i` and `s` are instruction indexes; 46 * 47 * The above equations are computed for each call chain and instruction 48 * index until state stops changing. 49 * - Additionally, in order to transfer "must_write" information from a 50 * subprogram to call instructions invoking this subprogram, 51 * the "must_write_acc" set is tracked for each (cc, i) tuple. 52 * A set of stack slots that are guaranteed to be written by this 53 * instruction or any of its successors (within the subprogram). 54 * The equation for "must_write_acc" propagation looks as follows: 55 * 56 * state[cc, i].must_write_acc = 57 * ∩ [state[cc, s].must_write_acc for s in bpf_insn_successors(i)] 58 * U state[cc, i].must_write 59 * 60 * (An intersection of all "must_write_acc" for instruction successors 61 * plus all "must_write" slots for the instruction itself). 62 * - After the propagation phase completes for a subprogram, information from 63 * (cc, 0) tuple (subprogram entry) is transferred to the caller's call chain: 64 * - "must_write_acc" set is intersected with the call site's "must_write" set; 65 * - "may_read" set is added to the call site's "may_read" set. 66 * - Any live stack queries must be taken after the propagation phase. 67 * - Accumulation and propagation phases can be entered multiple times, 68 * at any point in time: 69 * - "may_read" set only grows; 70 * - "must_write" set only shrinks; 71 * - for each visited verifier state with zero branches, all relevant 72 * read and write marks are already recorded by the analysis instance. 73 * 74 * Technically, the analysis is facilitated by the following data structures: 75 * - Call chain: for given verifier state, the call chain is a tuple of call 76 * instruction indexes leading to the current subprogram plus the subprogram 77 * entry point index. 78 * - Function instance: for a given call chain, for each instruction in 79 * the current subprogram, a mapping between instruction index and a 80 * set of "may_read", "must_write" and other marks accumulated for this 81 * instruction. 82 * - A hash table mapping call chains to function instances. 83 */ 84 85 struct callchain { 86 u32 callsites[MAX_CALL_FRAMES]; /* instruction pointer for each frame */ 87 /* cached subprog_info[*].start for functions owning the frames: 88 * - sp_starts[curframe] used to get insn relative index within current function; 89 * - sp_starts[0..current-1] used for fast callchain_frame_up(). 90 */ 91 u32 sp_starts[MAX_CALL_FRAMES]; 92 u32 curframe; /* depth of callsites and sp_starts arrays */ 93 }; 94 95 struct per_frame_masks { 96 u64 may_read; /* stack slots that may be read by this instruction */ 97 u64 must_write; /* stack slots written by this instruction */ 98 u64 must_write_acc; /* stack slots written by this instruction and its successors */ 99 u64 live_before; /* stack slots that may be read by this insn and its successors */ 100 }; 101 102 /* 103 * A function instance created for a specific callchain. 104 * Encapsulates read and write marks for each instruction in the function. 105 * Marks are tracked for each frame in the callchain. 106 */ 107 struct func_instance { 108 struct hlist_node hl_node; 109 struct callchain callchain; 110 u32 insn_cnt; /* cached number of insns in the function */ 111 bool updated; 112 bool must_write_dropped; 113 /* Per frame, per instruction masks, frames allocated lazily. */ 114 struct per_frame_masks *frames[MAX_CALL_FRAMES]; 115 /* For each instruction a flag telling if "must_write" had been initialized for it. */ 116 bool *must_write_set; 117 }; 118 119 struct live_stack_query { 120 struct func_instance *instances[MAX_CALL_FRAMES]; /* valid in range [0..curframe] */ 121 u32 curframe; 122 u32 insn_idx; 123 }; 124 125 struct bpf_liveness { 126 DECLARE_HASHTABLE(func_instances, 8); /* maps callchain to func_instance */ 127 struct live_stack_query live_stack_query; /* cache to avoid repetitive ht lookups */ 128 /* Cached instance corresponding to env->cur_state, avoids per-instruction ht lookup */ 129 struct func_instance *cur_instance; 130 /* 131 * Below fields are used to accumulate stack write marks for instruction at 132 * @write_insn_idx before submitting the marks to @cur_instance. 133 */ 134 u64 write_masks_acc[MAX_CALL_FRAMES]; 135 u32 write_insn_idx; 136 }; 137 138 /* Compute callchain corresponding to state @st at depth @frameno */ 139 static void compute_callchain(struct bpf_verifier_env *env, struct bpf_verifier_state *st, 140 struct callchain *callchain, u32 frameno) 141 { 142 struct bpf_subprog_info *subprog_info = env->subprog_info; 143 u32 i; 144 145 memset(callchain, 0, sizeof(*callchain)); 146 for (i = 0; i <= frameno; i++) { 147 callchain->sp_starts[i] = subprog_info[st->frame[i]->subprogno].start; 148 if (i < st->curframe) 149 callchain->callsites[i] = st->frame[i + 1]->callsite; 150 } 151 callchain->curframe = frameno; 152 callchain->callsites[callchain->curframe] = callchain->sp_starts[callchain->curframe]; 153 } 154 155 static u32 hash_callchain(struct callchain *callchain) 156 { 157 return jhash2(callchain->callsites, callchain->curframe, 0); 158 } 159 160 static bool same_callsites(struct callchain *a, struct callchain *b) 161 { 162 int i; 163 164 if (a->curframe != b->curframe) 165 return false; 166 for (i = a->curframe; i >= 0; i--) 167 if (a->callsites[i] != b->callsites[i]) 168 return false; 169 return true; 170 } 171 172 /* 173 * Find existing or allocate new function instance corresponding to @callchain. 174 * Instances are accumulated in env->liveness->func_instances and persist 175 * until the end of the verification process. 176 */ 177 static struct func_instance *__lookup_instance(struct bpf_verifier_env *env, 178 struct callchain *callchain) 179 { 180 struct bpf_liveness *liveness = env->liveness; 181 struct bpf_subprog_info *subprog; 182 struct func_instance *result; 183 u32 subprog_sz, size, key; 184 185 key = hash_callchain(callchain); 186 hash_for_each_possible(liveness->func_instances, result, hl_node, key) 187 if (same_callsites(&result->callchain, callchain)) 188 return result; 189 190 subprog = bpf_find_containing_subprog(env, callchain->sp_starts[callchain->curframe]); 191 subprog_sz = (subprog + 1)->start - subprog->start; 192 size = sizeof(struct func_instance); 193 result = kvzalloc(size, GFP_KERNEL_ACCOUNT); 194 if (!result) 195 return ERR_PTR(-ENOMEM); 196 result->must_write_set = kvzalloc_objs(*result->must_write_set, 197 subprog_sz, GFP_KERNEL_ACCOUNT); 198 if (!result->must_write_set) { 199 kvfree(result); 200 return ERR_PTR(-ENOMEM); 201 } 202 memcpy(&result->callchain, callchain, sizeof(*callchain)); 203 result->insn_cnt = subprog_sz; 204 hash_add(liveness->func_instances, &result->hl_node, key); 205 return result; 206 } 207 208 static struct func_instance *lookup_instance(struct bpf_verifier_env *env, 209 struct bpf_verifier_state *st, 210 u32 frameno) 211 { 212 struct callchain callchain; 213 214 compute_callchain(env, st, &callchain, frameno); 215 return __lookup_instance(env, &callchain); 216 } 217 218 int bpf_stack_liveness_init(struct bpf_verifier_env *env) 219 { 220 env->liveness = kvzalloc_obj(*env->liveness, GFP_KERNEL_ACCOUNT); 221 if (!env->liveness) 222 return -ENOMEM; 223 hash_init(env->liveness->func_instances); 224 return 0; 225 } 226 227 void bpf_stack_liveness_free(struct bpf_verifier_env *env) 228 { 229 struct func_instance *instance; 230 struct hlist_node *tmp; 231 int bkt, i; 232 233 if (!env->liveness) 234 return; 235 hash_for_each_safe(env->liveness->func_instances, bkt, tmp, instance, hl_node) { 236 for (i = 0; i <= instance->callchain.curframe; i++) 237 kvfree(instance->frames[i]); 238 kvfree(instance->must_write_set); 239 kvfree(instance); 240 } 241 kvfree(env->liveness); 242 } 243 244 /* 245 * Convert absolute instruction index @insn_idx to an index relative 246 * to start of the function corresponding to @instance. 247 */ 248 static int relative_idx(struct func_instance *instance, u32 insn_idx) 249 { 250 return insn_idx - instance->callchain.sp_starts[instance->callchain.curframe]; 251 } 252 253 static struct per_frame_masks *get_frame_masks(struct func_instance *instance, 254 u32 frame, u32 insn_idx) 255 { 256 if (!instance->frames[frame]) 257 return NULL; 258 259 return &instance->frames[frame][relative_idx(instance, insn_idx)]; 260 } 261 262 static struct per_frame_masks *alloc_frame_masks(struct bpf_verifier_env *env, 263 struct func_instance *instance, 264 u32 frame, u32 insn_idx) 265 { 266 struct per_frame_masks *arr; 267 268 if (!instance->frames[frame]) { 269 arr = kvzalloc_objs(*arr, instance->insn_cnt, 270 GFP_KERNEL_ACCOUNT); 271 instance->frames[frame] = arr; 272 if (!arr) 273 return ERR_PTR(-ENOMEM); 274 } 275 return get_frame_masks(instance, frame, insn_idx); 276 } 277 278 void bpf_reset_live_stack_callchain(struct bpf_verifier_env *env) 279 { 280 env->liveness->cur_instance = NULL; 281 } 282 283 /* If @env->liveness->cur_instance is null, set it to instance corresponding to @env->cur_state. */ 284 static int ensure_cur_instance(struct bpf_verifier_env *env) 285 { 286 struct bpf_liveness *liveness = env->liveness; 287 struct func_instance *instance; 288 289 if (liveness->cur_instance) 290 return 0; 291 292 instance = lookup_instance(env, env->cur_state, env->cur_state->curframe); 293 if (IS_ERR(instance)) 294 return PTR_ERR(instance); 295 296 liveness->cur_instance = instance; 297 return 0; 298 } 299 300 /* Accumulate may_read masks for @frame at @insn_idx */ 301 static int mark_stack_read(struct bpf_verifier_env *env, 302 struct func_instance *instance, u32 frame, u32 insn_idx, u64 mask) 303 { 304 struct per_frame_masks *masks; 305 u64 new_may_read; 306 307 masks = alloc_frame_masks(env, instance, frame, insn_idx); 308 if (IS_ERR(masks)) 309 return PTR_ERR(masks); 310 new_may_read = masks->may_read | mask; 311 if (new_may_read != masks->may_read && 312 ((new_may_read | masks->live_before) != masks->live_before)) 313 instance->updated = true; 314 masks->may_read |= mask; 315 return 0; 316 } 317 318 int bpf_mark_stack_read(struct bpf_verifier_env *env, u32 frame, u32 insn_idx, u64 mask) 319 { 320 int err; 321 322 err = ensure_cur_instance(env); 323 err = err ?: mark_stack_read(env, env->liveness->cur_instance, frame, insn_idx, mask); 324 return err; 325 } 326 327 static void reset_stack_write_marks(struct bpf_verifier_env *env, 328 struct func_instance *instance, u32 insn_idx) 329 { 330 struct bpf_liveness *liveness = env->liveness; 331 int i; 332 333 liveness->write_insn_idx = insn_idx; 334 for (i = 0; i <= instance->callchain.curframe; i++) 335 liveness->write_masks_acc[i] = 0; 336 } 337 338 int bpf_reset_stack_write_marks(struct bpf_verifier_env *env, u32 insn_idx) 339 { 340 struct bpf_liveness *liveness = env->liveness; 341 int err; 342 343 err = ensure_cur_instance(env); 344 if (err) 345 return err; 346 347 reset_stack_write_marks(env, liveness->cur_instance, insn_idx); 348 return 0; 349 } 350 351 void bpf_mark_stack_write(struct bpf_verifier_env *env, u32 frame, u64 mask) 352 { 353 env->liveness->write_masks_acc[frame] |= mask; 354 } 355 356 static int commit_stack_write_marks(struct bpf_verifier_env *env, 357 struct func_instance *instance) 358 { 359 struct bpf_liveness *liveness = env->liveness; 360 u32 idx, frame, curframe, old_must_write; 361 struct per_frame_masks *masks; 362 u64 mask; 363 364 if (!instance) 365 return 0; 366 367 curframe = instance->callchain.curframe; 368 idx = relative_idx(instance, liveness->write_insn_idx); 369 for (frame = 0; frame <= curframe; frame++) { 370 mask = liveness->write_masks_acc[frame]; 371 /* avoid allocating frames for zero masks */ 372 if (mask == 0 && !instance->must_write_set[idx]) 373 continue; 374 masks = alloc_frame_masks(env, instance, frame, liveness->write_insn_idx); 375 if (IS_ERR(masks)) 376 return PTR_ERR(masks); 377 old_must_write = masks->must_write; 378 /* 379 * If instruction at this callchain is seen for a first time, set must_write equal 380 * to @mask. Otherwise take intersection with the previous value. 381 */ 382 if (instance->must_write_set[idx]) 383 mask &= old_must_write; 384 if (old_must_write != mask) { 385 masks->must_write = mask; 386 instance->updated = true; 387 } 388 if (old_must_write & ~mask) 389 instance->must_write_dropped = true; 390 } 391 instance->must_write_set[idx] = true; 392 liveness->write_insn_idx = 0; 393 return 0; 394 } 395 396 /* 397 * Merge stack writes marks in @env->liveness->write_masks_acc 398 * with information already in @env->liveness->cur_instance. 399 */ 400 int bpf_commit_stack_write_marks(struct bpf_verifier_env *env) 401 { 402 return commit_stack_write_marks(env, env->liveness->cur_instance); 403 } 404 405 static char *fmt_callchain(struct bpf_verifier_env *env, struct callchain *callchain) 406 { 407 char *buf_end = env->tmp_str_buf + sizeof(env->tmp_str_buf); 408 char *buf = env->tmp_str_buf; 409 int i; 410 411 buf += snprintf(buf, buf_end - buf, "("); 412 for (i = 0; i <= callchain->curframe; i++) 413 buf += snprintf(buf, buf_end - buf, "%s%d", i ? "," : "", callchain->callsites[i]); 414 snprintf(buf, buf_end - buf, ")"); 415 return env->tmp_str_buf; 416 } 417 418 static void log_mask_change(struct bpf_verifier_env *env, struct callchain *callchain, 419 char *pfx, u32 frame, u32 insn_idx, u64 old, u64 new) 420 { 421 u64 changed_bits = old ^ new; 422 u64 new_ones = new & changed_bits; 423 u64 new_zeros = ~new & changed_bits; 424 425 if (!changed_bits) 426 return; 427 bpf_log(&env->log, "%s frame %d insn %d ", fmt_callchain(env, callchain), frame, insn_idx); 428 if (new_ones) { 429 bpf_fmt_stack_mask(env->tmp_str_buf, sizeof(env->tmp_str_buf), new_ones); 430 bpf_log(&env->log, "+%s %s ", pfx, env->tmp_str_buf); 431 } 432 if (new_zeros) { 433 bpf_fmt_stack_mask(env->tmp_str_buf, sizeof(env->tmp_str_buf), new_zeros); 434 bpf_log(&env->log, "-%s %s", pfx, env->tmp_str_buf); 435 } 436 bpf_log(&env->log, "\n"); 437 } 438 439 int bpf_jmp_offset(struct bpf_insn *insn) 440 { 441 u8 code = insn->code; 442 443 if (code == (BPF_JMP32 | BPF_JA)) 444 return insn->imm; 445 return insn->off; 446 } 447 448 __diag_push(); 449 __diag_ignore_all("-Woverride-init", "Allow field initialization overrides for opcode_info_tbl"); 450 451 /* 452 * Returns an array of instructions succ, with succ->items[0], ..., 453 * succ->items[n-1] with successor instructions, where n=succ->cnt 454 */ 455 inline struct bpf_iarray * 456 bpf_insn_successors(struct bpf_verifier_env *env, u32 idx) 457 { 458 static const struct opcode_info { 459 bool can_jump; 460 bool can_fallthrough; 461 } opcode_info_tbl[256] = { 462 [0 ... 255] = {.can_jump = false, .can_fallthrough = true}, 463 #define _J(code, ...) \ 464 [BPF_JMP | code] = __VA_ARGS__, \ 465 [BPF_JMP32 | code] = __VA_ARGS__ 466 467 _J(BPF_EXIT, {.can_jump = false, .can_fallthrough = false}), 468 _J(BPF_JA, {.can_jump = true, .can_fallthrough = false}), 469 _J(BPF_JEQ, {.can_jump = true, .can_fallthrough = true}), 470 _J(BPF_JNE, {.can_jump = true, .can_fallthrough = true}), 471 _J(BPF_JLT, {.can_jump = true, .can_fallthrough = true}), 472 _J(BPF_JLE, {.can_jump = true, .can_fallthrough = true}), 473 _J(BPF_JGT, {.can_jump = true, .can_fallthrough = true}), 474 _J(BPF_JGE, {.can_jump = true, .can_fallthrough = true}), 475 _J(BPF_JSGT, {.can_jump = true, .can_fallthrough = true}), 476 _J(BPF_JSGE, {.can_jump = true, .can_fallthrough = true}), 477 _J(BPF_JSLT, {.can_jump = true, .can_fallthrough = true}), 478 _J(BPF_JSLE, {.can_jump = true, .can_fallthrough = true}), 479 _J(BPF_JCOND, {.can_jump = true, .can_fallthrough = true}), 480 _J(BPF_JSET, {.can_jump = true, .can_fallthrough = true}), 481 #undef _J 482 }; 483 struct bpf_prog *prog = env->prog; 484 struct bpf_insn *insn = &prog->insnsi[idx]; 485 const struct opcode_info *opcode_info; 486 struct bpf_iarray *succ, *jt; 487 int insn_sz; 488 489 jt = env->insn_aux_data[idx].jt; 490 if (unlikely(jt)) 491 return jt; 492 493 /* pre-allocated array of size up to 2; reset cnt, as it may have been used already */ 494 succ = env->succ; 495 succ->cnt = 0; 496 497 opcode_info = &opcode_info_tbl[BPF_CLASS(insn->code) | BPF_OP(insn->code)]; 498 insn_sz = bpf_is_ldimm64(insn) ? 2 : 1; 499 if (opcode_info->can_fallthrough) 500 succ->items[succ->cnt++] = idx + insn_sz; 501 502 if (opcode_info->can_jump) 503 succ->items[succ->cnt++] = idx + bpf_jmp_offset(insn) + 1; 504 505 return succ; 506 } 507 508 __diag_pop(); 509 510 static struct func_instance *get_outer_instance(struct bpf_verifier_env *env, 511 struct func_instance *instance) 512 { 513 struct callchain callchain = instance->callchain; 514 515 /* Adjust @callchain to represent callchain one frame up */ 516 callchain.callsites[callchain.curframe] = 0; 517 callchain.sp_starts[callchain.curframe] = 0; 518 callchain.curframe--; 519 callchain.callsites[callchain.curframe] = callchain.sp_starts[callchain.curframe]; 520 return __lookup_instance(env, &callchain); 521 } 522 523 static u32 callchain_subprog_start(struct callchain *callchain) 524 { 525 return callchain->sp_starts[callchain->curframe]; 526 } 527 528 /* 529 * Transfer @may_read and @must_write_acc marks from the first instruction of @instance, 530 * to the call instruction in function instance calling @instance. 531 */ 532 static int propagate_to_outer_instance(struct bpf_verifier_env *env, 533 struct func_instance *instance) 534 { 535 struct callchain *callchain = &instance->callchain; 536 u32 this_subprog_start, callsite, frame; 537 struct func_instance *outer_instance; 538 struct per_frame_masks *insn; 539 int err; 540 541 this_subprog_start = callchain_subprog_start(callchain); 542 outer_instance = get_outer_instance(env, instance); 543 if (IS_ERR(outer_instance)) 544 return PTR_ERR(outer_instance); 545 callsite = callchain->callsites[callchain->curframe - 1]; 546 547 reset_stack_write_marks(env, outer_instance, callsite); 548 for (frame = 0; frame < callchain->curframe; frame++) { 549 insn = get_frame_masks(instance, frame, this_subprog_start); 550 if (!insn) 551 continue; 552 bpf_mark_stack_write(env, frame, insn->must_write_acc); 553 err = mark_stack_read(env, outer_instance, frame, callsite, insn->live_before); 554 if (err) 555 return err; 556 } 557 commit_stack_write_marks(env, outer_instance); 558 return 0; 559 } 560 561 static inline bool update_insn(struct bpf_verifier_env *env, 562 struct func_instance *instance, u32 frame, u32 insn_idx) 563 { 564 struct bpf_insn_aux_data *aux = env->insn_aux_data; 565 u64 new_before, new_after, must_write_acc; 566 struct per_frame_masks *insn, *succ_insn; 567 struct bpf_iarray *succ; 568 u32 s; 569 bool changed; 570 571 succ = bpf_insn_successors(env, insn_idx); 572 if (succ->cnt == 0) 573 return false; 574 575 changed = false; 576 insn = get_frame_masks(instance, frame, insn_idx); 577 new_before = 0; 578 new_after = 0; 579 /* 580 * New "must_write_acc" is an intersection of all "must_write_acc" 581 * of successors plus all "must_write" slots of instruction itself. 582 */ 583 must_write_acc = U64_MAX; 584 for (s = 0; s < succ->cnt; ++s) { 585 succ_insn = get_frame_masks(instance, frame, succ->items[s]); 586 new_after |= succ_insn->live_before; 587 must_write_acc &= succ_insn->must_write_acc; 588 } 589 must_write_acc |= insn->must_write; 590 /* 591 * New "live_before" is a union of all "live_before" of successors 592 * minus slots written by instruction plus slots read by instruction. 593 */ 594 new_before = (new_after & ~insn->must_write) | insn->may_read; 595 changed |= new_before != insn->live_before; 596 changed |= must_write_acc != insn->must_write_acc; 597 if (unlikely(env->log.level & BPF_LOG_LEVEL2) && 598 (insn->may_read || insn->must_write || 599 insn_idx == callchain_subprog_start(&instance->callchain) || 600 aux[insn_idx].prune_point)) { 601 log_mask_change(env, &instance->callchain, "live", 602 frame, insn_idx, insn->live_before, new_before); 603 log_mask_change(env, &instance->callchain, "written", 604 frame, insn_idx, insn->must_write_acc, must_write_acc); 605 } 606 insn->live_before = new_before; 607 insn->must_write_acc = must_write_acc; 608 return changed; 609 } 610 611 /* Fixed-point computation of @live_before and @must_write_acc marks */ 612 static int update_instance(struct bpf_verifier_env *env, struct func_instance *instance) 613 { 614 u32 i, frame, po_start, po_end, cnt, this_subprog_start; 615 struct callchain *callchain = &instance->callchain; 616 int *insn_postorder = env->cfg.insn_postorder; 617 struct bpf_subprog_info *subprog; 618 struct per_frame_masks *insn; 619 bool changed; 620 int err; 621 622 this_subprog_start = callchain_subprog_start(callchain); 623 /* 624 * If must_write marks were updated must_write_acc needs to be reset 625 * (to account for the case when new must_write sets became smaller). 626 */ 627 if (instance->must_write_dropped) { 628 for (frame = 0; frame <= callchain->curframe; frame++) { 629 if (!instance->frames[frame]) 630 continue; 631 632 for (i = 0; i < instance->insn_cnt; i++) { 633 insn = get_frame_masks(instance, frame, this_subprog_start + i); 634 insn->must_write_acc = 0; 635 } 636 } 637 } 638 639 subprog = bpf_find_containing_subprog(env, this_subprog_start); 640 po_start = subprog->postorder_start; 641 po_end = (subprog + 1)->postorder_start; 642 cnt = 0; 643 /* repeat until fixed point is reached */ 644 do { 645 cnt++; 646 changed = false; 647 for (frame = 0; frame <= instance->callchain.curframe; frame++) { 648 if (!instance->frames[frame]) 649 continue; 650 651 for (i = po_start; i < po_end; i++) 652 changed |= update_insn(env, instance, frame, insn_postorder[i]); 653 } 654 } while (changed); 655 656 if (env->log.level & BPF_LOG_LEVEL2) 657 bpf_log(&env->log, "%s live stack update done in %d iterations\n", 658 fmt_callchain(env, callchain), cnt); 659 660 /* transfer marks accumulated for outer frames to outer func instance (caller) */ 661 if (callchain->curframe > 0) { 662 err = propagate_to_outer_instance(env, instance); 663 if (err) 664 return err; 665 } 666 667 return 0; 668 } 669 670 /* 671 * Prepare all callchains within @env->cur_state for querying. 672 * This function should be called after each verifier.c:pop_stack() 673 * and whenever verifier.c:do_check_insn() processes subprogram exit. 674 * This would guarantee that visited verifier states with zero branches 675 * have their bpf_mark_stack_{read,write}() effects propagated in 676 * @env->liveness. 677 */ 678 int bpf_update_live_stack(struct bpf_verifier_env *env) 679 { 680 struct func_instance *instance; 681 int err, frame; 682 683 bpf_reset_live_stack_callchain(env); 684 for (frame = env->cur_state->curframe; frame >= 0; --frame) { 685 instance = lookup_instance(env, env->cur_state, frame); 686 if (IS_ERR(instance)) 687 return PTR_ERR(instance); 688 689 if (instance->updated) { 690 err = update_instance(env, instance); 691 if (err) 692 return err; 693 instance->updated = false; 694 instance->must_write_dropped = false; 695 } 696 } 697 return 0; 698 } 699 700 static bool is_live_before(struct func_instance *instance, u32 insn_idx, u32 frameno, u32 spi) 701 { 702 struct per_frame_masks *masks; 703 704 masks = get_frame_masks(instance, frameno, insn_idx); 705 return masks && (masks->live_before & BIT(spi)); 706 } 707 708 int bpf_live_stack_query_init(struct bpf_verifier_env *env, struct bpf_verifier_state *st) 709 { 710 struct live_stack_query *q = &env->liveness->live_stack_query; 711 struct func_instance *instance; 712 u32 frame; 713 714 memset(q, 0, sizeof(*q)); 715 for (frame = 0; frame <= st->curframe; frame++) { 716 instance = lookup_instance(env, st, frame); 717 if (IS_ERR(instance)) 718 return PTR_ERR(instance); 719 q->instances[frame] = instance; 720 } 721 q->curframe = st->curframe; 722 q->insn_idx = st->insn_idx; 723 return 0; 724 } 725 726 bool bpf_stack_slot_alive(struct bpf_verifier_env *env, u32 frameno, u32 spi) 727 { 728 /* 729 * Slot is alive if it is read before q->st->insn_idx in current func instance, 730 * or if for some outer func instance: 731 * - alive before callsite if callsite calls callback, otherwise 732 * - alive after callsite 733 */ 734 struct live_stack_query *q = &env->liveness->live_stack_query; 735 struct func_instance *instance, *curframe_instance; 736 u32 i, callsite; 737 bool alive; 738 739 curframe_instance = q->instances[q->curframe]; 740 if (is_live_before(curframe_instance, q->insn_idx, frameno, spi)) 741 return true; 742 743 for (i = frameno; i < q->curframe; i++) { 744 callsite = curframe_instance->callchain.callsites[i]; 745 instance = q->instances[i]; 746 alive = bpf_calls_callback(env, callsite) 747 ? is_live_before(instance, callsite, frameno, spi) 748 : is_live_before(instance, callsite + 1, frameno, spi); 749 if (alive) 750 return true; 751 } 752 753 return false; 754 } 755