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
mark_subprog_changes_pkt_data(struct bpf_verifier_env * env,int off)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
mark_subprog_might_sleep(struct bpf_verifier_env * env,int off)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
mark_subprog_might_throw(struct bpf_verifier_env * env,int off)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 */
merge_callee_effects(struct bpf_verifier_env * env,int t,int w)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 */
push_insn(int t,int w,int e,struct bpf_verifier_env * env)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
visit_func_call_insn(int t,struct bpf_insn * insns,struct bpf_verifier_env * env,bool visit_callee)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
bpf_iarray_realloc(struct bpf_iarray * old,size_t n_elem)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
copy_insn_array(struct bpf_map * map,u32 start,u32 end,u32 * items)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
cmp_ptr_to_u32(const void * a,const void * b)221 static int cmp_ptr_to_u32(const void *a, const void *b)
222 {
223 return *(u32 *)a - *(u32 *)b;
224 }
225
sort_insn_array_uniq(u32 * items,int cnt)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 */
bpf_copy_insn_array_uniq(struct bpf_map * map,u32 start,u32 end,u32 * off)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 */
jt_from_map(struct bpf_map * map)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 */
jt_from_subprog(struct bpf_verifier_env * env,int subprog_start,int subprog_end)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 *
create_jt(int t,struct bpf_verifier_env * env)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" */
visit_gotox_insn(int t,struct bpf_verifier_env * env)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 */
visit_abnormal_return_insn(struct bpf_verifier_env * env,int t)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 */
visit_insn(int t,struct bpf_verifier_env * env)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 */
bpf_check_cfg(struct bpf_verifier_env * env)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 */
bpf_compute_postorder(struct bpf_verifier_env * env)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 */
bpf_compute_scc(struct bpf_verifier_env * env)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