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 */
compute_callchain(struct bpf_verifier_env * env,struct bpf_verifier_state * st,struct callchain * callchain,u32 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
hash_callchain(struct callchain * callchain)155 static u32 hash_callchain(struct callchain *callchain)
156 {
157 return jhash2(callchain->callsites, callchain->curframe, 0);
158 }
159
same_callsites(struct callchain * a,struct callchain * b)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 */
__lookup_instance(struct bpf_verifier_env * env,struct callchain * callchain)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
lookup_instance(struct bpf_verifier_env * env,struct bpf_verifier_state * st,u32 frameno)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
bpf_stack_liveness_init(struct bpf_verifier_env * env)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
bpf_stack_liveness_free(struct bpf_verifier_env * env)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 */
relative_idx(struct func_instance * instance,u32 insn_idx)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
get_frame_masks(struct func_instance * instance,u32 frame,u32 insn_idx)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
alloc_frame_masks(struct bpf_verifier_env * env,struct func_instance * instance,u32 frame,u32 insn_idx)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
bpf_reset_live_stack_callchain(struct bpf_verifier_env * env)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. */
ensure_cur_instance(struct bpf_verifier_env * env)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 */
mark_stack_read(struct bpf_verifier_env * env,struct func_instance * instance,u32 frame,u32 insn_idx,u64 mask)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
bpf_mark_stack_read(struct bpf_verifier_env * env,u32 frame,u32 insn_idx,u64 mask)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
reset_stack_write_marks(struct bpf_verifier_env * env,struct func_instance * instance,u32 insn_idx)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
bpf_reset_stack_write_marks(struct bpf_verifier_env * env,u32 insn_idx)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
bpf_mark_stack_write(struct bpf_verifier_env * env,u32 frame,u64 mask)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
commit_stack_write_marks(struct bpf_verifier_env * env,struct func_instance * instance)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 */
bpf_commit_stack_write_marks(struct bpf_verifier_env * env)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
fmt_callchain(struct bpf_verifier_env * env,struct callchain * callchain)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
log_mask_change(struct bpf_verifier_env * env,struct callchain * callchain,char * pfx,u32 frame,u32 insn_idx,u64 old,u64 new)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
bpf_jmp_offset(struct bpf_insn * insn)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 *
bpf_insn_successors(struct bpf_verifier_env * env,u32 idx)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
get_outer_instance(struct bpf_verifier_env * env,struct func_instance * instance)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
callchain_subprog_start(struct callchain * callchain)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 */
propagate_to_outer_instance(struct bpf_verifier_env * env,struct func_instance * instance)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
update_insn(struct bpf_verifier_env * env,struct func_instance * instance,u32 frame,u32 insn_idx)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 */
update_instance(struct bpf_verifier_env * env,struct func_instance * instance)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 */
bpf_update_live_stack(struct bpf_verifier_env * env)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
is_live_before(struct func_instance * instance,u32 insn_idx,u32 frameno,u32 spi)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
bpf_live_stack_query_init(struct bpf_verifier_env * env,struct bpf_verifier_state * st)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
bpf_stack_slot_alive(struct bpf_verifier_env * env,u32 frameno,u32 spi)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