1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
3
4 #include <linux/bpf.h>
5 #include <linux/bpf_verifier.h>
6 #include <linux/btf.h>
7 #include <linux/ctype.h>
8 #include <linux/kernel.h>
9 #include <linux/list.h>
10 #include <linux/seq_buf.h>
11 #include <linux/overflow.h>
12 #include <linux/slab.h>
13 #include <linux/stdarg.h>
14 #include <linux/string.h>
15
16 #include "disasm.h"
17 #include "diagnostics.h"
18
19 #define REGISTER_TYPE_SAFETY "Register Type Safety"
20 #define MEMORY_SAFETY "Memory Safety"
21 #define RESOURCE_LIFETIME_SAFETY "Resource Lifetime Safety"
22 #define CALL_TYPE_SAFETY "Call Type Safety"
23 #define EXECUTION_CONTEXT_SAFETY "Execution Context Safety"
24 #define PROGRAM_STRUCTURE "Program Structure"
25 #define POLICY "Policy"
26
27 #define BPF_DIAG_TEXT_WIDTH 100
28 #define BPF_DIAG_TEXT_INDENT " "
29 #define BPF_DIAG_CONTEXT 2
30 #define BPF_DIAG_CONTEXT_CNT (1 + BPF_DIAG_CONTEXT * 2)
31 #define BPF_DIAG_HISTORY_RENDER_MAX 64
32 #define BPF_DIAG_SOURCE_LANE_WIDTH 88
33 #define BPF_DIAG_TAB_WIDTH 8
34 #define BPF_DIAG_FMT_CHUNK_SIZE (PAGE_SIZE - sizeof(struct diag_fmt_chunk))
35 #define BPF_DIAG_FMT_BUF_SIZE 256
36 #define BPF_DIAG_EVENT_LOG_MAX_SIZE (64U << 20)
37 #define DISASM_LINE_LEN 160
38
39 enum bpf_diag_mod_target_kind {
40 BPF_DIAG_MOD_TARGET_NONE,
41 BPF_DIAG_MOD_TARGET_REG,
42 BPF_DIAG_MOD_TARGET_STACK_ARG,
43 BPF_DIAG_MOD_TARGET_STACK_SLOT,
44 BPF_DIAG_MOD_TARGET_STACK_RANGE,
45 };
46
47 struct bpf_diag_mod_target {
48 u32 frame_id;
49 union {
50 struct {
51 s16 min_off;
52 s16 max_off;
53 } range;
54 u16 spi;
55 u8 regno;
56 u8 stack_arg;
57 };
58 u8 frameno;
59 u8 kind;
60 };
61
diag_reg_target(u32 frame_id,u8 frameno,u8 regno)62 static struct bpf_diag_mod_target diag_reg_target(u32 frame_id, u8 frameno, u8 regno)
63 {
64 return (struct bpf_diag_mod_target){
65 .frame_id = frame_id,
66 .frameno = frameno,
67 .kind = BPF_DIAG_MOD_TARGET_REG,
68 .regno = regno,
69 };
70 }
71
diag_stack_arg_target(u32 frame_id,u8 frameno,u8 slot)72 static struct bpf_diag_mod_target diag_stack_arg_target(u32 frame_id, u8 frameno, u8 slot)
73 {
74 return (struct bpf_diag_mod_target){
75 .frame_id = frame_id,
76 .frameno = frameno,
77 .kind = BPF_DIAG_MOD_TARGET_STACK_ARG,
78 .stack_arg = slot,
79 };
80 }
81
diag_stack_slot_target(u32 frame_id,u8 frameno,u16 spi)82 static struct bpf_diag_mod_target diag_stack_slot_target(u32 frame_id, u8 frameno, u16 spi)
83 {
84 return (struct bpf_diag_mod_target){
85 .frame_id = frame_id,
86 .frameno = frameno,
87 .kind = BPF_DIAG_MOD_TARGET_STACK_SLOT,
88 .spi = spi,
89 };
90 }
91
diag_stack_range_target(u32 frame_id,u8 frameno,s16 min_off,s16 max_off)92 static struct bpf_diag_mod_target diag_stack_range_target(u32 frame_id, u8 frameno,
93 s16 min_off, s16 max_off)
94 {
95 return (struct bpf_diag_mod_target){
96 .frame_id = frame_id,
97 .frameno = frameno,
98 .kind = BPF_DIAG_MOD_TARGET_STACK_RANGE,
99 .range.min_off = min_off,
100 .range.max_off = max_off,
101 };
102 }
103
104 struct bpf_diag_reg_snapshot {
105 u32 type;
106 u32 btf_id;
107 const struct bpf_map *map_ptr;
108 const struct btf *btf;
109 struct tnum var_off;
110 struct cnum64 r64;
111 };
112
113 enum bpf_diag_history_kind {
114 BPF_DIAG_HISTORY_BRANCH,
115 BPF_DIAG_HISTORY_MOD,
116 BPF_DIAG_HISTORY_REF_ACQUIRE,
117 BPF_DIAG_HISTORY_REF_RELEASE,
118 BPF_DIAG_HISTORY_CONTEXT,
119 };
120
121 struct bpf_diag_history_event {
122 u32 insn_idx : 24;
123 u32 kind : 8;
124 u8 in_lineage : 1;
125 union {
126 struct {
127 bool cond_true;
128 } branch;
129 struct {
130 struct bpf_diag_mod_target target;
131 struct bpf_diag_mod_target origin;
132 struct bpf_diag_reg_snapshot old, new;
133 u8 reason;
134 bool origin_valid;
135 } mod;
136 struct {
137 u32 ref_id;
138 } ref;
139 struct {
140 u32 depth;
141 u8 kind;
142 bool enter;
143 } ctx;
144 };
145 };
146
147 enum bpf_diag_history_scope {
148 BPF_DIAG_HISTORY_SCOPE_REG,
149 BPF_DIAG_HISTORY_SCOPE_STACK_ARG,
150 BPF_DIAG_HISTORY_SCOPE_REF,
151 BPF_DIAG_HISTORY_SCOPE_CONTEXT,
152 };
153
154 struct bpf_diag_history_opts {
155 enum bpf_diag_history_scope scope;
156 u32 frame_id;
157 u32 frameno;
158 int regno;
159 int stack_arg_slot;
160 u32 ref_id;
161 enum bpf_diag_context_kind ctx_kind;
162 u32 ctx_depth;
163 };
164
165 static void diag_print_history(struct bpf_verifier_env *env,
166 const struct bpf_diag_history_opts *opts);
167 static bool diag_target_matches(const struct bpf_diag_mod_target *event_target,
168 const struct bpf_diag_mod_target *target);
169 static const char *diag_context_name(enum bpf_diag_context_kind kind);
170 struct disasm_line {
171 char text[DISASM_LINE_LEN];
172 int idx;
173 bool valid;
174 };
175
176 struct disasm_ctx {
177 struct bpf_verifier_env *env;
178 struct seq_buf seq;
179 };
180
181 struct diag_fmt_chunk {
182 struct list_head node;
183 struct seq_buf seq;
184 char data[];
185 };
186
187 struct diag_fmt_mark {
188 struct diag_fmt_chunk *chunk;
189 size_t len;
190 };
191
192 struct bpf_diag_log {
193 struct bpf_diag_history_event *events;
194 /* Sequence number of the oldest retained event on the active path. */
195 u64 first_seq;
196 u32 cnt;
197 u32 cap;
198 u32 head;
199 bool growth_failed;
200 };
201
202 struct bpf_diag_scratch {
203 struct bpf_linfo_source source_lines[BPF_DIAG_CONTEXT_CNT];
204 struct disasm_line disasm_lines[BPF_DIAG_CONTEXT_CNT];
205 };
206
207 struct bpf_diag_mod_scope {
208 struct bpf_reg_state target_reg_snapshot;
209 struct bpf_diag_mod_target target;
210 struct bpf_diag_mod_target origin;
211 enum bpf_diag_mod_reason reason;
212 u32 insn_idx;
213 bool active;
214 bool origin_valid;
215 };
216
217 struct bpf_diag {
218 struct bpf_diag_log log;
219 struct bpf_diag_scratch scratch;
220 struct list_head fmt_chunks;
221 struct bpf_diag_mod_scope mod;
222 u32 frame_id_gen;
223 };
224
bpf_diag_enabled(const struct bpf_verifier_env * env)225 bool bpf_diag_enabled(const struct bpf_verifier_env *env)
226 {
227 return env->log.level & BPF_LOG_LEVEL;
228 }
229
230 static void diag_write(struct bpf_verifier_env *env, const char *fmt, ...) __printf(2, 3);
231
bpf_diag_init(struct bpf_verifier_env * env)232 int bpf_diag_init(struct bpf_verifier_env *env)
233 {
234 if (!bpf_diag_enabled(env))
235 return 0;
236
237 env->diag = kzalloc_obj(struct bpf_diag, GFP_KERNEL_ACCOUNT);
238 if (!env->diag)
239 return -ENOMEM;
240
241 INIT_LIST_HEAD(&env->diag->fmt_chunks);
242 return 0;
243 }
244
bpf_diag_init_frame(struct bpf_verifier_env * env,struct bpf_func_state * state)245 void bpf_diag_init_frame(struct bpf_verifier_env *env, struct bpf_func_state *state)
246 {
247 if (env->diag)
248 state->diag_frame_id = ++env->diag->frame_id_gen;
249 }
250
diag_fmt_alloc(struct bpf_verifier_env * env,size_t size)251 static char *diag_fmt_alloc(struct bpf_verifier_env *env, size_t size)
252 {
253 struct bpf_diag *diag = env->diag;
254 struct diag_fmt_chunk *chunk;
255 size_t capacity, available;
256 char *buf;
257
258 if (!diag || !size || size > INT_MAX)
259 return NULL;
260
261 if (!list_empty(&diag->fmt_chunks)) {
262 chunk = list_last_entry(&diag->fmt_chunks, struct diag_fmt_chunk, node);
263 available = seq_buf_get_buf(&chunk->seq, &buf);
264 if (available >= size)
265 goto commit;
266 }
267
268 capacity = max_t(size_t, BPF_DIAG_FMT_CHUNK_SIZE, size);
269 chunk = kmalloc(struct_size(chunk, data, capacity), GFP_KERNEL_ACCOUNT);
270 if (!chunk)
271 return NULL;
272
273 seq_buf_init(&chunk->seq, chunk->data, capacity);
274 list_add_tail(&chunk->node, &diag->fmt_chunks);
275 available = seq_buf_get_buf(&chunk->seq, &buf);
276 if (WARN_ON_ONCE(available < size))
277 return NULL;
278
279 commit:
280 seq_buf_commit(&chunk->seq, size);
281 return buf;
282 }
283
bpf_diag_fmt_buf(struct bpf_verifier_env * env,size_t size)284 char *bpf_diag_fmt_buf(struct bpf_verifier_env *env, size_t size)
285 {
286 char *buf;
287
288 buf = diag_fmt_alloc(env, size);
289 if (buf)
290 buf[0] = '\0';
291 return buf;
292 }
293
bpf_diag_vfmt(struct bpf_verifier_env * env,const char * fmt,va_list args)294 const char *bpf_diag_vfmt(struct bpf_verifier_env *env, const char *fmt, va_list args)
295 {
296 va_list copy;
297 char *buf;
298 int len;
299
300 va_copy(copy, args);
301 len = vsnprintf(NULL, 0, fmt, copy);
302 va_end(copy);
303 if (len < 0 || len == INT_MAX)
304 return "";
305
306 buf = diag_fmt_alloc(env, len + 1);
307 if (buf)
308 vsnprintf(buf, len + 1, fmt, args);
309 return buf ?: "";
310 }
311
bpf_diag_fmt(struct bpf_verifier_env * env,const char * fmt,...)312 const char *bpf_diag_fmt(struct bpf_verifier_env *env, const char *fmt, ...)
313 {
314 const char *buf;
315 va_list args;
316
317 va_start(args, fmt);
318 buf = bpf_diag_vfmt(env, fmt, args);
319 va_end(args);
320 return buf;
321 }
322
diag_fmt_save(struct bpf_verifier_env * env)323 static struct diag_fmt_mark diag_fmt_save(struct bpf_verifier_env *env)
324 {
325 struct bpf_diag *diag = env->diag;
326 struct diag_fmt_mark mark = {};
327
328 if (!diag || list_empty(&diag->fmt_chunks))
329 return mark;
330
331 mark.chunk = list_last_entry(&diag->fmt_chunks, struct diag_fmt_chunk, node);
332 mark.len = mark.chunk->seq.len;
333 return mark;
334 }
335
diag_fmt_restore(struct bpf_verifier_env * env,struct diag_fmt_mark mark)336 static void diag_fmt_restore(struct bpf_verifier_env *env, struct diag_fmt_mark mark)
337 {
338 struct bpf_diag *diag = env->diag;
339 struct diag_fmt_chunk *chunk;
340
341 if (!diag)
342 return;
343
344 while (!list_empty(&diag->fmt_chunks)) {
345 chunk = list_last_entry(&diag->fmt_chunks, struct diag_fmt_chunk, node);
346 if (chunk == mark.chunk)
347 break;
348 list_del(&chunk->node);
349 kfree(chunk);
350 }
351
352 if (mark.chunk) {
353 mark.chunk->seq.len = mark.len;
354 seq_buf_str(&mark.chunk->seq);
355 }
356 }
357
bpf_diag_free(struct bpf_verifier_env * env)358 void bpf_diag_free(struct bpf_verifier_env *env)
359 {
360 struct bpf_diag *diag = env->diag;
361
362 if (!diag)
363 return;
364
365 diag_fmt_restore(env, (struct diag_fmt_mark){});
366 kvfree(diag->log.events);
367 kfree(diag);
368 env->diag = NULL;
369 }
370
diag_write(struct bpf_verifier_env * env,const char * fmt,...)371 static void diag_write(struct bpf_verifier_env *env, const char *fmt, ...)
372 {
373 va_list args;
374
375 if (!bpf_diag_enabled(env))
376 return;
377
378 va_start(args, fmt);
379 bpf_verifier_vlog(&env->log, fmt, args);
380 va_end(args);
381 }
382
log_end(const struct bpf_diag_log * log)383 static u64 log_end(const struct bpf_diag_log *log)
384 {
385 return log->first_seq + log->cnt;
386 }
387
log_pos(const struct bpf_diag_log * log,u32 idx)388 static u32 log_pos(const struct bpf_diag_log *log, u32 idx)
389 {
390 u32 pos = log->head + idx;
391
392 return pos < log->cap ? pos : pos - log->cap;
393 }
394
bpf_diag_event_log_save(struct bpf_verifier_env * env)395 u64 bpf_diag_event_log_save(struct bpf_verifier_env *env)
396 {
397 struct bpf_diag *diag = env->diag;
398
399 return diag ? log_end(&diag->log) : 0;
400 }
401
bpf_diag_event_log_restore(struct bpf_verifier_env * env,u64 log_pos)402 void bpf_diag_event_log_restore(struct bpf_verifier_env *env, u64 log_pos)
403 {
404 struct bpf_diag *diag = env->diag;
405 struct bpf_diag_log *log;
406 u64 end_seq;
407
408 if (!diag)
409 return;
410
411 log = &diag->log;
412 end_seq = log_end(log);
413 if (WARN_ON_ONCE(log_pos > end_seq))
414 log_pos = end_seq;
415
416 /*
417 * A deep abandoned path may have rotated away the shared prefix. In
418 * that case, restart with an empty retained suffix and remember that
419 * every event before the restored mark is unavailable.
420 */
421 if (log_pos <= log->first_seq) {
422 log->first_seq = log_pos;
423 log->head = 0;
424 log->cnt = 0;
425 return;
426 }
427
428 log->cnt = log_pos - log->first_seq;
429 }
430
bpf_diag_irq_depth(const struct bpf_verifier_state * state)431 u32 bpf_diag_irq_depth(const struct bpf_verifier_state *state)
432 {
433 u32 depth = 0;
434 int i;
435
436 for (i = 0; i < state->acquired_refs; i++) {
437 if (state->refs[i].type == REF_TYPE_IRQ)
438 depth++;
439 }
440
441 return depth;
442 }
443
diag_append_history(struct bpf_verifier_env * env,const struct bpf_diag_history_event * event)444 static void diag_append_history(struct bpf_verifier_env *env,
445 const struct bpf_diag_history_event *event)
446 {
447 struct bpf_diag_history_event *events;
448 struct bpf_diag *diag = env->diag;
449 struct bpf_diag_log *log;
450 u32 cap, max_events;
451
452 if (!diag)
453 return;
454 log = &diag->log;
455
456 if (log->cnt < log->cap) {
457 log->events[log_pos(log, log->cnt++)] = *event;
458 return;
459 }
460
461 max_events = BPF_DIAG_EVENT_LOG_MAX_SIZE / sizeof(*events);
462 if (log->growth_failed || log->cap == max_events)
463 goto rotate;
464
465 cap = min(log->cap ? log->cap * 2 : 64, max_events);
466 events = kvrealloc(log->events, array_size(cap, sizeof(*events)), GFP_KERNEL_ACCOUNT);
467 if (!events) {
468 log->growth_failed = true;
469 goto rotate;
470 }
471 log->events = events;
472 log->cap = cap;
473 log->events[log->cnt++] = *event;
474 return;
475
476 rotate:
477 if (log->cap) {
478 log->events[log->head++] = *event;
479 if (log->head == log->cap)
480 log->head = 0;
481 }
482 log->first_seq++;
483 }
484
diag_print_wrapped_prefixed(struct bpf_verifier_env * env,const char * first_prefix,const char * next_prefix,const char * text)485 static void diag_print_wrapped_prefixed(struct bpf_verifier_env *env, const char *first_prefix,
486 const char *next_prefix, const char *text)
487 {
488 const char *prefix = first_prefix;
489
490 while (*text) {
491 const char *line = text;
492 int prefix_len = strlen(prefix);
493 int text_width = BPF_DIAG_TEXT_WIDTH - prefix_len;
494 int len = 0, last_space = -1;
495
496 if (text_width < 1)
497 text_width = 1;
498
499 while (line[len] && line[len] != '\n' && len < text_width) {
500 if (line[len] == ' ')
501 last_space = len;
502 len++;
503 }
504
505 if (line[len] && line[len] != '\n' && line[len] != ' ' && last_space > 0)
506 len = last_space;
507
508 diag_write(env, "%s%.*s\n", prefix, len, line);
509
510 text = line + len;
511 while (*text == ' ')
512 text++;
513 if (*text == '\n')
514 text++;
515
516 prefix = next_prefix;
517 }
518 }
519
bpf_diag_fmt_btf_type(struct bpf_verifier_env * env,const struct btf * btf,u32 type_id)520 const char *bpf_diag_fmt_btf_type(struct bpf_verifier_env *env, const struct btf *btf, u32 type_id)
521 {
522 char *buf = bpf_diag_fmt_buf(env, BPF_DIAG_FMT_BUF_SIZE);
523 size_t len;
524 int ret;
525
526 if (!buf)
527 return "";
528
529 buf[0] = '\0';
530 ret = btf_type_name_to_buf(btf, type_id, buf, BPF_DIAG_FMT_BUF_SIZE);
531 if (ret < 0 || !buf[0]) {
532 scnprintf(buf, BPF_DIAG_FMT_BUF_SIZE, "BTF type ID %u", type_id);
533 return buf;
534 }
535
536 len = strlen(buf);
537 if (len && buf[len - 1] == '{')
538 buf[len - 1] = '\0';
539 return buf;
540 }
541
542 static void diag_vprint_indented(struct bpf_verifier_env *env, const char *fmt, va_list args)
543 __printf(2, 0);
544
diag_vprint_indented(struct bpf_verifier_env * env,const char * fmt,va_list args)545 static void diag_vprint_indented(struct bpf_verifier_env *env, const char *fmt, va_list args)
546 {
547 char *buf;
548
549 if (!bpf_diag_enabled(env))
550 return;
551
552 buf = kvasprintf(GFP_KERNEL_ACCOUNT, fmt, args);
553 if (!buf) {
554 diag_write(env, "%s<failed to allocate diagnostic text>\n", BPF_DIAG_TEXT_INDENT);
555 return;
556 }
557
558 diag_print_wrapped_prefixed(env, BPF_DIAG_TEXT_INDENT, BPF_DIAG_TEXT_INDENT, buf);
559 kfree(buf);
560 }
561
diag_line_width(unsigned int line)562 static int diag_line_width(unsigned int line)
563 {
564 int width = 1;
565
566 while (line >= 10) {
567 line /= 10;
568 width++;
569 }
570
571 return width;
572 }
573
diag_line_indent(const char * line)574 static int diag_line_indent(const char *line)
575 {
576 int indent = 0;
577
578 while (*line == ' ' || *line == '\t') {
579 if (*line == '\t')
580 indent = round_up(indent + 1, BPF_DIAG_TAB_WIDTH);
581 else
582 indent++;
583 line++;
584 }
585
586 return indent;
587 }
588
589 static void disasm_print(void *private_data, const char *fmt, ...) __printf(2, 3);
590
disasm_print(void * private_data,const char * fmt,...)591 static void disasm_print(void *private_data, const char *fmt, ...)
592 {
593 struct disasm_ctx *ctx = private_data;
594 va_list args;
595
596 va_start(args, fmt);
597 seq_buf_vprintf(&ctx->seq, fmt, args);
598 va_end(args);
599 }
600
disasm_kfunc_name(void * private_data,const struct bpf_insn * insn)601 static const char *disasm_kfunc_name(void *private_data, const struct bpf_insn *insn)
602 {
603 struct disasm_ctx *ctx = private_data;
604
605 return bpf_disasm_kfunc_name(ctx->env, insn);
606 }
607
format_disasm_line(struct bpf_verifier_env * env,int insn_idx,struct disasm_line * line)608 static void format_disasm_line(struct bpf_verifier_env *env, int insn_idx,
609 struct disasm_line *line)
610 {
611 struct disasm_ctx ctx = { .env = env };
612 struct bpf_insn *insn;
613 const struct bpf_insn_cbs cbs = {
614 .cb_call = disasm_kfunc_name,
615 .cb_print = disasm_print,
616 .private_data = &ctx,
617 };
618
619 line->idx = insn_idx;
620 line->valid = false;
621 seq_buf_init(&ctx.seq, line->text, sizeof(line->text));
622
623 if (insn_idx < 0 || insn_idx >= env->prog->len)
624 return;
625
626 if (insn_idx > 0 && bpf_is_ldimm64(&env->prog->insnsi[insn_idx - 1]))
627 return;
628
629 insn = &env->prog->insnsi[insn_idx];
630 if (bpf_is_ldimm64(insn) && insn_idx + 1 >= env->prog->len)
631 return;
632
633 print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);
634 seq_buf_str(&ctx.seq);
635 ctx.seq.len = strnlen(line->text, sizeof(line->text));
636 while (ctx.seq.len && line->text[ctx.seq.len - 1] == '\n')
637 seq_buf_pop(&ctx.seq);
638 seq_buf_str(&ctx.seq);
639
640 line->valid = true;
641 }
642
diag_format_source_text(char * buf,size_t size,const char * line,int width)643 static void diag_format_source_text(char *buf, size_t size, const char *line, int width)
644 {
645 int col = 0, len = 0;
646
647 if (!size)
648 return;
649 if (width <= 0) {
650 buf[0] = '\0';
651 return;
652 }
653
654 line = line ?: "...";
655 while (*line && col < width && len + 1 < size) {
656 if (*line == '\t') {
657 int next = round_up(col + 1, BPF_DIAG_TAB_WIDTH);
658
659 while (col < next && col < width && len + 1 < size) {
660 buf[len++] = ' ';
661 col++;
662 }
663 line++;
664 continue;
665 }
666
667 buf[len++] = *line++;
668 col++;
669 }
670
671 if (*line) {
672 int ellipsis_len = min(3, width);
673
674 while (len > 0 && col > width - ellipsis_len) {
675 len--;
676 col--;
677 }
678 while (ellipsis_len-- && len + 1 < size)
679 buf[len++] = '.';
680 }
681
682 buf[len] = '\0';
683 }
684
diag_format_source_lane(char * buf,size_t size,const char * source_prefix,int source_line_width,int line_num,const char * line)685 static void diag_format_source_lane(char *buf, size_t size, const char *source_prefix,
686 int source_line_width, int line_num, const char *line)
687 {
688 int len, text_width;
689
690 if (line_num <= 0) {
691 buf[0] = '\0';
692 return;
693 }
694
695 len = scnprintf(buf, size, "%s%*d | ", source_prefix, source_line_width, line_num);
696 text_width = BPF_DIAG_SOURCE_LANE_WIDTH - len;
697 diag_format_source_text(buf + len, size - len, line, text_width);
698 }
699
bpf_diag_header(struct bpf_verifier_env * env,const char * category,const char * problem)700 static void bpf_diag_header(struct bpf_verifier_env *env, const char *category,
701 const char *problem)
702 {
703 char first;
704
705 if (!bpf_diag_enabled(env))
706 return;
707
708 category = category ?: "Verifier Error";
709 problem = problem ?: "";
710
711 if (!problem[0]) {
712 diag_write(env, "\nVerification failed: %s\n", category);
713 return;
714 }
715
716 first = toupper(problem[0]);
717 diag_write(env, "\nVerification failed: %s: %c%s\n", category, first, problem + 1);
718 }
719
720 static void diag_reason(struct bpf_verifier_env *env, const char *fmt, ...) __printf(2, 3);
721 static void diag_suggestion(struct bpf_verifier_env *env, const char *fmt, ...)
722 __printf(2, 3);
723
diag_section(struct bpf_verifier_env * env,const char * title)724 static void diag_section(struct bpf_verifier_env *env, const char *title)
725 {
726 if (!bpf_diag_enabled(env))
727 return;
728
729 diag_write(env, "\n%s:\n", title);
730 }
731
diag_reason(struct bpf_verifier_env * env,const char * fmt,...)732 static void diag_reason(struct bpf_verifier_env *env, const char *fmt, ...)
733 {
734 va_list args;
735
736 if (!bpf_diag_enabled(env))
737 return;
738
739 diag_section(env, "Reason");
740
741 va_start(args, fmt);
742 diag_vprint_indented(env, fmt, args);
743 va_end(args);
744 }
745
diag_suggestion(struct bpf_verifier_env * env,const char * fmt,...)746 static void diag_suggestion(struct bpf_verifier_env *env, const char *fmt, ...)
747 {
748 va_list args;
749
750 if (!bpf_diag_enabled(env))
751 return;
752
753 diag_section(env, "Suggestion");
754
755 va_start(args, fmt);
756 diag_vprint_indented(env, fmt, args);
757 va_end(args);
758 diag_write(env, "\n");
759 }
760
diag_print_source_annotation(struct bpf_verifier_env * env,int line_width,int indent,const char * label,const char * msg)761 static void diag_print_source_annotation(struct bpf_verifier_env *env, int line_width, int indent,
762 const char *label, const char *msg)
763 {
764 const char *first_prefix, *next_prefix, *text;
765
766 indent = min_t(int, indent, max_t(int, 0, BPF_DIAG_SOURCE_LANE_WIDTH - line_width - 8));
767 text = bpf_diag_fmt(env, "%s: %s", label, msg);
768 first_prefix = bpf_diag_fmt(env, " %*s | %*s^-- ", line_width + 4, "", indent, "");
769 next_prefix = bpf_diag_fmt(env, " %*s | %*s ", line_width + 4, "", indent, "");
770
771 diag_print_wrapped_prefixed(env, first_prefix, next_prefix, text);
772 }
773
diag_print_insn_context(struct bpf_verifier_env * env,u32 insn_idx,struct disasm_line * disasm_lines)774 static void diag_print_insn_context(struct bpf_verifier_env *env, u32 insn_idx,
775 struct disasm_line *disasm_lines)
776 {
777 int insn_width = diag_line_width(env->prog->len ? env->prog->len - 1 : 0);
778 int i;
779
780 for (i = 0; i < BPF_DIAG_CONTEXT_CNT; i++) {
781 int row = i - BPF_DIAG_CONTEXT;
782
783 format_disasm_line(env, insn_idx + row, &disasm_lines[i]);
784 }
785
786 diag_write(env, " Instruction context:\n");
787 for (i = 0; i < BPF_DIAG_CONTEXT_CNT; i++) {
788 struct disasm_line *line = &disasm_lines[i];
789
790 if (line->valid)
791 diag_write(env, " %s%*d | %s\n",
792 line->idx == insn_idx ? ">>> " : " ",
793 insn_width, line->idx, line->text);
794 }
795 }
796
bpf_diag_source(struct bpf_verifier_env * env,u32 insn_idx,const char * label,const char * fmt,...)797 static void bpf_diag_source(struct bpf_verifier_env *env, u32 insn_idx, const char *label,
798 const char *fmt, ...)
799 {
800 struct bpf_diag_scratch *scratch;
801 struct bpf_linfo_source *source_lines;
802 struct disasm_line *disasm_lines;
803 struct bpf_linfo_source src = {};
804 struct diag_fmt_mark mark;
805 const struct bpf_line_info *linfo;
806 const struct bpf_subprog_info *subprog;
807 struct btf *btf = env->prog->aux->btf;
808 char *source_lane;
809 const char *msg;
810 const char *func;
811 int start_line, end_line, width, indent, subprogno, linfo_start, linfo_end, i;
812 va_list args;
813
814 if (!bpf_diag_enabled(env))
815 return;
816 if (!env->diag)
817 return;
818
819 mark = diag_fmt_save(env);
820 label = label ?: "note";
821 scratch = &env->diag->scratch;
822 source_lines = scratch->source_lines;
823 disasm_lines = scratch->disasm_lines;
824 memset(source_lines, 0, sizeof(scratch->source_lines));
825 memset(disasm_lines, 0, sizeof(scratch->disasm_lines));
826
827 va_start(args, fmt);
828 msg = bpf_diag_vfmt(env, fmt, args);
829 va_end(args);
830 if (!*msg)
831 msg = "<failed to allocate diagnostic text>";
832
833 linfo = bpf_find_linfo(env->prog, insn_idx);
834 if (btf && linfo)
835 bpf_get_linfo_source(btf, linfo, &src);
836 if (!src.file || !*src.file) {
837 diag_write(env, " insn %u\n", insn_idx);
838 goto out_annotation;
839 }
840
841 subprog = bpf_find_containing_subprog(env, insn_idx);
842 subprogno = subprog ? subprog - env->subprog_info : -ENOENT;
843 func = subprogno >= 0 ? bpf_subprog_name(env, subprogno) : NULL;
844 if (func && *func)
845 diag_write(env, " %s @ %s:%d:%d\n", func, src.file, src.line_num, src.line_col);
846 else
847 diag_write(env, " %s:%d:%d\n", src.file, src.line_num, src.line_col);
848 if (!src.line || !*src.line)
849 goto out_annotation;
850
851 start_line = src.line_num - BPF_DIAG_CONTEXT;
852 end_line = src.line_num + BPF_DIAG_CONTEXT;
853 width = diag_line_width(end_line);
854 indent = diag_line_indent(src.line);
855 for (i = 0; i < BPF_DIAG_CONTEXT_CNT; i++)
856 source_lines[i].line_num = start_line + i;
857
858 linfo = env->prog->aux->linfo;
859 linfo_start = subprog ? subprog->linfo_idx : 0;
860 linfo_end = subprogno >= 0 && subprogno + 1 < env->subprog_cnt ?
861 env->subprog_info[subprogno + 1].linfo_idx : env->prog->aux->nr_linfo;
862 for (i = linfo_start; i < linfo_end; i++) {
863 struct bpf_linfo_source line_src;
864 int idx;
865
866 bpf_get_linfo_source(btf, &linfo[i], &line_src);
867 if (line_src.file_name_off != src.file_name_off ||
868 line_src.line_num < start_line || line_src.line_num > end_line ||
869 !line_src.line || !*line_src.line)
870 continue;
871
872 idx = line_src.line_num - start_line;
873 if (!source_lines[idx].line)
874 source_lines[idx] = line_src;
875 }
876
877 diag_write(env, " Source context:\n");
878 source_lane = bpf_diag_fmt_buf(env, BPF_DIAG_FMT_BUF_SIZE);
879 if (!source_lane)
880 goto out_restore;
881 for (i = 0; i < BPF_DIAG_CONTEXT_CNT; i++) {
882 const char *source_prefix;
883
884 source_prefix = source_lines[i].line_num == src.line_num ? ">>> " : " ";
885 diag_format_source_lane(source_lane, BPF_DIAG_FMT_BUF_SIZE, source_prefix, width,
886 source_lines[i].line_num, source_lines[i].line);
887 diag_write(env, " %s\n", source_lane);
888 if (source_lines[i].line_num == src.line_num)
889 diag_print_source_annotation(env, width, indent, label, msg);
890 }
891 diag_print_insn_context(env, insn_idx, disasm_lines);
892 goto out_restore;
893
894 out_annotation:
895 diag_print_source_annotation(env, 0, 0, label, msg);
896 diag_print_insn_context(env, insn_idx, disasm_lines);
897 out_restore:
898 diag_fmt_restore(env, mark);
899 }
900
diag_current_frame(const struct bpf_verifier_env * env)901 static const struct bpf_func_state *diag_current_frame(const struct bpf_verifier_env *env)
902 {
903 return env->cur_state->frame[env->cur_state->curframe];
904 }
905
bpf_diag_register_type(struct bpf_verifier_env * env,u32 insn_idx,int regno,const char * problem,const char * reason,const char * suggestion)906 void bpf_diag_register_type(struct bpf_verifier_env *env, u32 insn_idx, int regno,
907 const char *problem, const char *reason, const char *suggestion)
908 {
909 const struct bpf_func_state *frame = diag_current_frame(env);
910 struct bpf_diag_history_opts opts = {
911 .scope = BPF_DIAG_HISTORY_SCOPE_REG,
912 .frame_id = frame->diag_frame_id,
913 .frameno = frame->frameno,
914 .regno = regno,
915 };
916
917 bpf_diag_header(env, REGISTER_TYPE_SAFETY, problem);
918 diag_reason(env, "%s", reason);
919
920 diag_section(env, "At");
921 bpf_diag_source(env, insn_idx, "error", "%s", problem);
922
923 if (regno >= 0)
924 diag_print_history(env, &opts);
925
926 diag_suggestion(env, "%s", suggestion);
927 }
928
bpf_diag_reg_type_plain(struct bpf_verifier_env * env,enum bpf_reg_type type)929 const char *bpf_diag_reg_type_plain(struct bpf_verifier_env *env, enum bpf_reg_type type)
930 {
931 switch (base_type(type)) {
932 case NOT_INIT:
933 return "an uninitialized value";
934 case SCALAR_VALUE:
935 return "an integer scalar";
936 case PTR_TO_CTX:
937 return "a context pointer";
938 case PTR_TO_STACK:
939 return "a stack pointer";
940 case PTR_TO_MAP_VALUE:
941 if (type_may_be_null(type))
942 return "a nullable map value pointer";
943 return "a map value pointer";
944 case PTR_TO_MEM:
945 if (type_may_be_null(type))
946 return "a nullable memory pointer";
947 return "a memory pointer";
948 case PTR_TO_BTF_ID:
949 if (type_may_be_null(type))
950 return "a nullable kernel object pointer";
951 if (type_is_non_owning_ref(type))
952 return "a borrowed allocated object pointer";
953 if (type_is_ptr_alloc_obj(type))
954 return "an owned allocated object pointer";
955 if (type_flag(type) & PTR_UNTRUSTED)
956 return "an untrusted kernel object pointer";
957 return "a kernel object pointer";
958 default:
959 return reg_type_str(env, type);
960 }
961 }
962
diag_arg_ordinal(int argno)963 static const char *diag_arg_ordinal(int argno)
964 {
965 switch (argno) {
966 case 1:
967 return "first";
968 case 2:
969 return "second";
970 case 3:
971 return "third";
972 case 4:
973 return "fourth";
974 case 5:
975 return "fifth";
976 case 6:
977 return "sixth";
978 case 7:
979 return "seventh";
980 case 8:
981 return "eighth";
982 case 9:
983 return "ninth";
984 case 10:
985 return "tenth";
986 case 11:
987 return "eleventh";
988 case 12:
989 return "twelfth";
990 default:
991 return NULL;
992 }
993 }
994
bpf_diag_call_type(struct bpf_verifier_env * env,u32 insn_idx,int argno,int regno,int stack_arg_slot,const char * call_name,const char * arg_name,const char * reason,const char * suggestion)995 void bpf_diag_call_type(struct bpf_verifier_env *env, u32 insn_idx, int argno, int regno,
996 int stack_arg_slot, const char *call_name, const char *arg_name,
997 const char *reason, const char *suggestion)
998 {
999 const struct bpf_func_state *frame = diag_current_frame(env);
1000 struct bpf_diag_history_opts opts = {
1001 .frame_id = frame->diag_frame_id,
1002 .frameno = frame->frameno,
1003 };
1004 const char *ordinal = diag_arg_ordinal(argno);
1005 const char *arg_desc;
1006 bool print_history = true;
1007
1008 if (regno >= 0) {
1009 opts.scope = BPF_DIAG_HISTORY_SCOPE_REG;
1010 opts.regno = regno;
1011 } else if (stack_arg_slot >= 0) {
1012 opts.scope = BPF_DIAG_HISTORY_SCOPE_STACK_ARG;
1013 opts.stack_arg_slot = stack_arg_slot;
1014 } else {
1015 print_history = false;
1016 }
1017
1018 if (ordinal && arg_name)
1019 arg_desc = bpf_diag_fmt(env, "%s argument (%s)", ordinal, arg_name);
1020 else if (ordinal)
1021 arg_desc = bpf_diag_fmt(env, "%s argument", ordinal);
1022 else if (arg_name)
1023 arg_desc = bpf_diag_fmt(env, "argument %s", arg_name);
1024 else
1025 arg_desc = "argument";
1026
1027 bpf_diag_header(env, CALL_TYPE_SAFETY, "invalid call argument");
1028 diag_reason(env, "The %s to %s does not satisfy the verifier contract: %s.",
1029 arg_desc, call_name, reason);
1030
1031 diag_section(env, "At");
1032 bpf_diag_source(env, insn_idx, "error", "invalid %s for %s", arg_desc, call_name);
1033
1034 if (print_history)
1035 diag_print_history(env, &opts);
1036
1037 diag_suggestion(env, "%s", suggestion);
1038 }
1039
diag_context_constraint(enum bpf_diag_context_kind kind)1040 static const char *diag_context_constraint(enum bpf_diag_context_kind kind)
1041 {
1042 switch (kind) {
1043 case BPF_DIAG_CONTEXT_RCU:
1044 return "RCU read-side critical sections cannot call operations that may sleep";
1045 case BPF_DIAG_CONTEXT_PREEMPT:
1046 return "preemption-disabled code cannot call operations that may sleep";
1047 case BPF_DIAG_CONTEXT_IRQ:
1048 return "IRQ-disabled code cannot call operations that may sleep";
1049 case BPF_DIAG_CONTEXT_LOCK:
1050 return "code holding a BPF spin lock cannot call operations that may sleep";
1051 case BPF_DIAG_CONTEXT_NONE:
1052 default:
1053 return NULL;
1054 }
1055 }
1056
diag_active_context(struct bpf_verifier_env * env,u32 depth,const char * context)1057 static const char *diag_active_context(struct bpf_verifier_env *env, u32 depth,
1058 const char *context)
1059 {
1060 if (depth == 1)
1061 return bpf_diag_fmt(env, "an active %s (depth 1)", context);
1062 return bpf_diag_fmt(env, "%u active %ss (depth %u)", depth, context, depth);
1063 }
1064
diag_context_depth(struct bpf_verifier_env * env,enum bpf_diag_context_kind kind)1065 static u32 diag_context_depth(struct bpf_verifier_env *env, enum bpf_diag_context_kind kind)
1066 {
1067 switch (kind) {
1068 case BPF_DIAG_CONTEXT_RCU:
1069 return env->cur_state->active_rcu_locks;
1070 case BPF_DIAG_CONTEXT_PREEMPT:
1071 return env->cur_state->active_preempt_locks;
1072 case BPF_DIAG_CONTEXT_IRQ:
1073 return bpf_diag_irq_depth(env->cur_state);
1074 case BPF_DIAG_CONTEXT_LOCK:
1075 return env->cur_state->active_locks;
1076 case BPF_DIAG_CONTEXT_NONE:
1077 default:
1078 return 0;
1079 }
1080 }
1081
bpf_diag_ctx_forbidden(struct bpf_verifier_env * env,u32 insn_idx,const char * operation,const char * suggestion)1082 void bpf_diag_ctx_forbidden(struct bpf_verifier_env *env, u32 insn_idx,
1083 const char *operation, const char *suggestion)
1084 {
1085 struct bpf_diag_history_opts opts;
1086 enum bpf_diag_context_kind ctx_kind;
1087 const char *constraint, *context;
1088 u32 depth;
1089
1090 if (env->cur_state->active_rcu_locks)
1091 ctx_kind = BPF_DIAG_CONTEXT_RCU;
1092 else if (env->cur_state->active_preempt_locks)
1093 ctx_kind = BPF_DIAG_CONTEXT_PREEMPT;
1094 else if (env->cur_state->active_irq_id)
1095 ctx_kind = BPF_DIAG_CONTEXT_IRQ;
1096 else if (env->cur_state->active_locks)
1097 ctx_kind = BPF_DIAG_CONTEXT_LOCK;
1098 else
1099 ctx_kind = BPF_DIAG_CONTEXT_NONE;
1100
1101 depth = diag_context_depth(env, ctx_kind);
1102 opts = (struct bpf_diag_history_opts) {
1103 .scope = BPF_DIAG_HISTORY_SCOPE_CONTEXT,
1104 .ctx_kind = ctx_kind,
1105 .ctx_depth = depth,
1106 };
1107 constraint = diag_context_constraint(ctx_kind);
1108 context = diag_context_name(ctx_kind);
1109
1110 bpf_diag_header(env, EXECUTION_CONTEXT_SAFETY,
1111 "operation is not allowed in this context");
1112 if (constraint) {
1113 if (depth) {
1114 diag_reason(
1115 env, "The operation %s cannot be used in %s because %s. This path is still inside %s.",
1116 operation, context, constraint, diag_active_context(env, depth, context));
1117 } else {
1118 diag_reason(env, "The operation %s cannot be used in %s because %s.",
1119 operation, context, constraint);
1120 }
1121 } else {
1122 diag_reason(env, "The operation %s cannot be used in %s.", operation,
1123 context);
1124 }
1125
1126 diag_section(env, "At");
1127 bpf_diag_source(env, insn_idx, "error", "%s is not allowed in %s", operation,
1128 context);
1129
1130 if (ctx_kind != BPF_DIAG_CONTEXT_NONE)
1131 diag_print_history(env, &opts);
1132
1133 diag_suggestion(env, "%s", suggestion);
1134 }
1135
bpf_diag_ctx_active(struct bpf_verifier_env * env,u32 insn_idx,const char * operation,enum bpf_diag_context_kind ctx_kind,const char * suggestion)1136 void bpf_diag_ctx_active(struct bpf_verifier_env *env, u32 insn_idx, const char *operation,
1137 enum bpf_diag_context_kind ctx_kind, const char *suggestion)
1138 {
1139 u32 depth = diag_context_depth(env, ctx_kind);
1140 struct bpf_diag_history_opts opts = {
1141 .scope = BPF_DIAG_HISTORY_SCOPE_CONTEXT,
1142 .ctx_kind = ctx_kind,
1143 .ctx_depth = depth,
1144 };
1145 const char *context = diag_context_name(ctx_kind);
1146
1147 bpf_diag_header(env, EXECUTION_CONTEXT_SAFETY,
1148 "operation is not allowed in this context");
1149 diag_reason(
1150 env, "The operation %s cannot be used while this path is still inside %s. Leave the region before this operation.",
1151 operation, diag_active_context(env, depth, context));
1152
1153 diag_section(env, "At");
1154 bpf_diag_source(env, insn_idx, "error", "%s is not allowed before leaving %s",
1155 operation, context);
1156
1157 diag_print_history(env, &opts);
1158
1159 diag_suggestion(env, "%s", suggestion);
1160 }
1161
bpf_diag_ctx_required(struct bpf_verifier_env * env,u32 insn_idx,const char * operation,enum bpf_diag_context_kind ctx_kind,const char * suggestion)1162 void bpf_diag_ctx_required(struct bpf_verifier_env *env, u32 insn_idx, const char *operation,
1163 enum bpf_diag_context_kind ctx_kind, const char *suggestion)
1164 {
1165 const char *context = diag_context_name(ctx_kind);
1166
1167 bpf_diag_header(env, EXECUTION_CONTEXT_SAFETY, "required context is not active");
1168 diag_reason(env, "The operation %s requires an active %s, but this path is outside one.",
1169 operation, context);
1170
1171 diag_section(env, "At");
1172 bpf_diag_source(env, insn_idx, "error", "%s requires %s", operation, context);
1173
1174 diag_suggestion(env, "%s", suggestion);
1175 }
1176
bpf_diag_ctx_underflow(struct bpf_verifier_env * env,u32 insn_idx,const char * operation,enum bpf_diag_context_kind ctx_kind,const char * suggestion)1177 void bpf_diag_ctx_underflow(struct bpf_verifier_env *env, u32 insn_idx,
1178 const char *operation, enum bpf_diag_context_kind ctx_kind,
1179 const char *suggestion)
1180 {
1181 struct bpf_diag_history_opts opts = {
1182 .scope = BPF_DIAG_HISTORY_SCOPE_CONTEXT,
1183 .ctx_kind = ctx_kind,
1184 };
1185 const char *context = diag_context_name(ctx_kind);
1186
1187 bpf_diag_header(env, EXECUTION_CONTEXT_SAFETY, "unmatched context exit");
1188 diag_reason(
1189 env, "The operation %s tries to leave %s, but this path has no active %s to leave. The current depth is 0.",
1190 operation, context, context);
1191
1192 diag_section(env, "At");
1193 bpf_diag_source(env, insn_idx, "error", "%s has no matching enter on this path",
1194 operation);
1195
1196 diag_print_history(env, &opts);
1197
1198 diag_suggestion(env, "%s", suggestion);
1199 }
1200
bpf_diag_program_structure(struct bpf_verifier_env * env,u32 insn_idx,const char * problem,const char * suggestion,const char * reason_fmt,...)1201 void bpf_diag_program_structure(struct bpf_verifier_env *env, u32 insn_idx,
1202 const char *problem, const char *suggestion,
1203 const char *reason_fmt, ...)
1204 {
1205 va_list args;
1206
1207 bpf_diag_header(env, PROGRAM_STRUCTURE, problem);
1208 diag_section(env, "Reason");
1209
1210 va_start(args, reason_fmt);
1211 diag_vprint_indented(env, reason_fmt, args);
1212 va_end(args);
1213
1214 diag_section(env, "At");
1215 bpf_diag_source(env, insn_idx, "error", "%s", problem);
1216
1217 diag_suggestion(env, "%s", suggestion);
1218 }
1219
bpf_diag_policy(struct bpf_verifier_env * env,u32 insn_idx,const char * operation,const char * reason,const char * suggestion)1220 void bpf_diag_policy(struct bpf_verifier_env *env, u32 insn_idx, const char *operation,
1221 const char *reason, const char *suggestion)
1222 {
1223 bpf_diag_header(env, POLICY, "operation is not allowed");
1224 diag_reason(env, "The %s is not allowed: %s.", operation, reason);
1225
1226 diag_section(env, "At");
1227 bpf_diag_source(env, insn_idx, "error", "policy check failed for %s", operation);
1228
1229 diag_suggestion(env, "%s", suggestion);
1230 }
1231
bpf_diag_invalid_deref(struct bpf_verifier_env * env,u32 insn_idx,int regno,const char * reg_name,const struct bpf_reg_state * reg,enum bpf_diag_invalid_deref_kind kind,s64 offset)1232 void bpf_diag_invalid_deref(struct bpf_verifier_env *env, u32 insn_idx, int regno,
1233 const char *reg_name, const struct bpf_reg_state *reg,
1234 enum bpf_diag_invalid_deref_kind kind, s64 offset)
1235 {
1236 const struct bpf_func_state *frame = diag_current_frame(env);
1237 struct bpf_diag_history_opts opts = {
1238 .scope = BPF_DIAG_HISTORY_SCOPE_REG,
1239 .frame_id = frame->diag_frame_id,
1240 .frameno = frame->frameno,
1241 .regno = regno,
1242 };
1243 const char *type_name = bpf_diag_reg_type_plain(env, reg->type);
1244
1245 bpf_diag_header(env, REGISTER_TYPE_SAFETY, "invalid dereference");
1246
1247 switch (kind) {
1248 case BPF_DIAG_DEREF_SCALAR:
1249 diag_reason(env, "%s is an integer scalar here, not a pointer to memory.",
1250 reg_name);
1251 break;
1252 case BPF_DIAG_DEREF_NULLABLE_PTR:
1253 diag_reason(
1254 env, "%s may be NULL here (%s). The program could dereference NULL on this path, so the verifier cannot prove this access is safe.",
1255 reg_name, type_name);
1256 break;
1257 case BPF_DIAG_DEREF_MODIFIED_PTR:
1258 diag_reason(
1259 env, "%s has offset %lld here, but this pointer type must be dereferenced in its original form.",
1260 reg_name, offset);
1261 break;
1262 case BPF_DIAG_DEREF_INVALID_PTR:
1263 default:
1264 diag_reason(
1265 env, "%s has type %s here, which is not valid for this memory access.",
1266 reg_name, type_name);
1267 break;
1268 }
1269
1270 diag_section(env, "At");
1271 if (kind == BPF_DIAG_DEREF_MODIFIED_PTR)
1272 bpf_diag_source(env, insn_idx, "error",
1273 "dereference requires the original %s pointer", type_name);
1274 else
1275 bpf_diag_source(env, insn_idx, "error", "invalid dereference of %s (%s)",
1276 reg_name, type_name);
1277
1278 if (regno >= 0)
1279 diag_print_history(env, &opts);
1280
1281 switch (kind) {
1282 case BPF_DIAG_DEREF_NULLABLE_PTR:
1283 diag_suggestion(
1284 env, "Add a NULL check before the access and dereference the pointer only on the non-NULL path.");
1285 break;
1286 case BPF_DIAG_DEREF_MODIFIED_PTR:
1287 diag_suggestion(
1288 env, "Preserve the original pointer in another register, or use only offsets this pointer type permits before dereferencing it.");
1289 break;
1290 case BPF_DIAG_DEREF_SCALAR:
1291 case BPF_DIAG_DEREF_INVALID_PTR:
1292 default:
1293 diag_suggestion(
1294 env, "Preserve a pointer-valued register where needed, or reload and revalidate the pointer after scalar arithmetic, helper calls, or other operations that can invalidate it.");
1295 break;
1296 }
1297 }
1298
bpf_diag_unreadable_reg(struct bpf_verifier_env * env,u32 insn_idx,int regno)1299 void bpf_diag_unreadable_reg(struct bpf_verifier_env *env, u32 insn_idx, int regno)
1300 {
1301 const struct bpf_func_state *frame = diag_current_frame(env);
1302 struct bpf_diag_history_opts opts = {
1303 .scope = BPF_DIAG_HISTORY_SCOPE_REG,
1304 .frame_id = frame->diag_frame_id,
1305 .frameno = frame->frameno,
1306 .regno = regno,
1307 };
1308 const struct bpf_diag_log *log = env->diag ? &env->diag->log : NULL;
1309 struct bpf_diag_mod_target target;
1310 bool invalidated = false;
1311 int i;
1312
1313 target = diag_reg_target(opts.frame_id, opts.frameno, regno);
1314 for (i = log ? log->cnt : 0; i > 0; i--) {
1315 const struct bpf_diag_history_event *event;
1316
1317 event = &log->events[log_pos(log, i - 1)];
1318
1319 if (event->kind != BPF_DIAG_HISTORY_MOD ||
1320 !diag_target_matches(&event->mod.target, &target))
1321 continue;
1322 invalidated = event->mod.new.type == NOT_INIT;
1323 break;
1324 }
1325
1326 bpf_diag_header(env, REGISTER_TYPE_SAFETY, "unreadable register");
1327 if (invalidated)
1328 diag_reason(
1329 env, "R%d is not readable here. A previous operation invalidated this register, so the verifier cannot use it as an input.",
1330 regno);
1331 else if (log && !log->first_seq)
1332 diag_reason(env,
1333 "R%d has never been initialized on this path, so the verifier cannot use it as an input.",
1334 regno);
1335 else
1336 diag_reason(
1337 env, "R%d is not readable here. It may never have been initialized, or an earlier operation may have invalidated it.",
1338 regno);
1339
1340 diag_section(env, "At");
1341 bpf_diag_source(env, insn_idx, "error", "R%d is not readable", regno);
1342
1343 if (regno >= 0)
1344 diag_print_history(env, &opts);
1345
1346 if (invalidated)
1347 diag_suggestion(
1348 env, "Avoid using the register after it is invalidated, or initialize it again before this instruction.");
1349 else if (log && !log->first_seq)
1350 diag_suggestion(env, "Initialize R%d on every path before this instruction.", regno);
1351 else
1352 diag_suggestion(
1353 env, "Initialize the register on every path, or initialize it again after any operation that invalidates it.");
1354 }
1355
diag_stack_argno(u8 slot)1356 static int diag_stack_argno(u8 slot)
1357 {
1358 return MAX_BPF_FUNC_REG_ARGS + slot + 1;
1359 }
1360
diag_format_stack_arg(char * buf,size_t size,u8 slot,const char * arg_name)1361 static void diag_format_stack_arg(char *buf, size_t size, u8 slot, const char *arg_name)
1362 {
1363 int argno = diag_stack_argno(slot);
1364 const char *ordinal = diag_arg_ordinal(argno);
1365
1366 if (ordinal && arg_name)
1367 scnprintf(buf, size, "outgoing stack argument %u (%s argument, %s)", slot + 1,
1368 ordinal, arg_name);
1369 else if (ordinal)
1370 scnprintf(buf, size, "outgoing stack argument %u (%s argument)", slot + 1, ordinal);
1371 else if (arg_name)
1372 scnprintf(buf, size, "outgoing stack argument %u (%s)", slot + 1, arg_name);
1373 else
1374 scnprintf(buf, size, "outgoing stack argument %u", slot + 1);
1375 }
1376
bpf_diag_stack_arg_uninit(struct bpf_verifier_env * env,u32 insn_idx,int nargs,int stack_arg_slot,const char * callee_name,const char * arg_name)1377 void bpf_diag_stack_arg_uninit(struct bpf_verifier_env *env, u32 insn_idx, int nargs,
1378 int stack_arg_slot, const char *callee_name,
1379 const char *arg_name)
1380 {
1381 const struct bpf_func_state *frame = diag_current_frame(env);
1382 struct bpf_diag_history_opts opts = {
1383 .scope = BPF_DIAG_HISTORY_SCOPE_STACK_ARG,
1384 .frame_id = frame->diag_frame_id,
1385 .frameno = frame->frameno,
1386 .stack_arg_slot = stack_arg_slot,
1387 };
1388 const char *arg_buf;
1389
1390 arg_buf = bpf_diag_fmt_buf(env, BPF_DIAG_FMT_BUF_SIZE);
1391 if (arg_buf)
1392 diag_format_stack_arg((char *)arg_buf, BPF_DIAG_FMT_BUF_SIZE, stack_arg_slot,
1393 arg_name);
1394 else
1395 arg_buf = "";
1396 bpf_diag_header(env, REGISTER_TYPE_SAFETY, "missing stack argument");
1397 if (callee_name && *callee_name)
1398 diag_reason(
1399 env, "Function %s expects %d arguments, but %s is not initialized at this call.",
1400 callee_name, nargs, arg_buf);
1401 else
1402 diag_reason(
1403 env, "The callee expects %d arguments, but %s is not initialized at this call.",
1404 nargs, arg_buf);
1405
1406 diag_section(env, "At");
1407 bpf_diag_source(env, insn_idx, "error", "%s is not initialized", arg_buf);
1408
1409 if (stack_arg_slot >= 0)
1410 diag_print_history(env, &opts);
1411
1412 diag_suggestion(
1413 env, "Write the outgoing stack argument after any operation that may invalidate stored pointer values, and before making this call.");
1414 }
1415
bpf_diag_memory(struct bpf_verifier_env * env,u32 insn_idx,const char * problem,const char * reason,const char * suggestion)1416 void bpf_diag_memory(struct bpf_verifier_env *env, u32 insn_idx, const char *problem,
1417 const char *reason, const char *suggestion)
1418 {
1419 bpf_diag_header(env, MEMORY_SAFETY, problem);
1420 diag_reason(env, "%s", reason);
1421
1422 diag_section(env, "At");
1423 bpf_diag_source(env, insn_idx, "error", "%s", problem);
1424
1425 diag_suggestion(env, "%s", suggestion);
1426 }
1427
bpf_diag_record_branch(struct bpf_verifier_env * env,u32 insn_idx,bool cond_true)1428 void bpf_diag_record_branch(struct bpf_verifier_env *env, u32 insn_idx, bool cond_true)
1429 {
1430 struct bpf_diag_history_event event = {
1431 .insn_idx = insn_idx,
1432 .kind = BPF_DIAG_HISTORY_BRANCH,
1433 .branch = {
1434 .cond_true = cond_true,
1435 },
1436 };
1437
1438 diag_append_history(env, &event);
1439 }
1440
diag_snapshot_reg(struct bpf_diag_reg_snapshot * snapshot,const struct bpf_reg_state * reg)1441 static void diag_snapshot_reg(struct bpf_diag_reg_snapshot *snapshot,
1442 const struct bpf_reg_state *reg)
1443 {
1444 snapshot->type = reg->type;
1445 if (type_is_map_ptr(reg->type))
1446 snapshot->map_ptr = reg->map_ptr;
1447 if (base_type(reg->type) == PTR_TO_BTF_ID && reg->btf && reg->btf_id) {
1448 snapshot->btf_id = reg->btf_id;
1449 snapshot->btf = reg->btf;
1450 }
1451 snapshot->var_off = reg->var_off;
1452 snapshot->r64 = reg->r64;
1453 }
1454
diag_mod_insn_origin(struct bpf_verifier_env * env,u32 insn_idx,const struct bpf_diag_mod_target * target,struct bpf_diag_mod_target * origin)1455 static bool diag_mod_insn_origin(struct bpf_verifier_env *env, u32 insn_idx,
1456 const struct bpf_diag_mod_target *target,
1457 struct bpf_diag_mod_target *origin)
1458 {
1459 const struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
1460 u8 class = BPF_CLASS(insn->code);
1461 const struct bpf_func_state *state;
1462
1463 if (target->kind == BPF_DIAG_MOD_TARGET_REG && (class == BPF_ALU || class == BPF_ALU64) &&
1464 BPF_OP(insn->code) == BPF_MOV && BPF_SRC(insn->code) == BPF_X) {
1465 *origin = diag_reg_target(target->frame_id, target->frameno, insn->src_reg);
1466 return true;
1467 }
1468
1469 if ((target->kind != BPF_DIAG_MOD_TARGET_STACK_ARG &&
1470 target->kind != BPF_DIAG_MOD_TARGET_STACK_SLOT) ||
1471 class != BPF_STX)
1472 return false;
1473
1474 state = env->cur_state->frame[env->cur_state->curframe];
1475 *origin = diag_reg_target(state->diag_frame_id, state->frameno, insn->src_reg);
1476 return true;
1477 }
1478
diag_mod_keeps_lineage(struct bpf_verifier_env * env,const struct bpf_diag_history_event * event)1479 static bool diag_mod_keeps_lineage(struct bpf_verifier_env *env,
1480 const struct bpf_diag_history_event *event)
1481 {
1482 const struct bpf_insn *insn;
1483 u8 class;
1484
1485 if (event->mod.reason != BPF_DIAG_MOD_WRITE ||
1486 event->mod.target.kind != BPF_DIAG_MOD_TARGET_REG)
1487 return false;
1488
1489 insn = &env->prog->insnsi[event->insn_idx];
1490 class = BPF_CLASS(insn->code);
1491 if (class != BPF_ALU && class != BPF_ALU64)
1492 return false;
1493
1494 switch (BPF_OP(insn->code)) {
1495 case BPF_ADD:
1496 case BPF_SUB:
1497 case BPF_MUL:
1498 case BPF_OR:
1499 case BPF_AND:
1500 case BPF_LSH:
1501 case BPF_RSH:
1502 case BPF_ARSH:
1503 case BPF_XOR:
1504 case BPF_NEG:
1505 case BPF_END:
1506 return true;
1507 default:
1508 return false;
1509 }
1510 }
1511
diag_record_mod(struct bpf_verifier_env * env,u32 insn_idx,struct bpf_diag_mod_target target,enum bpf_diag_mod_reason reason,const struct bpf_reg_state * old_reg,const struct bpf_reg_state * new_reg,const struct bpf_diag_mod_target * origin)1512 static void diag_record_mod(struct bpf_verifier_env *env, u32 insn_idx,
1513 struct bpf_diag_mod_target target,
1514 enum bpf_diag_mod_reason reason,
1515 const struct bpf_reg_state *old_reg,
1516 const struct bpf_reg_state *new_reg,
1517 const struct bpf_diag_mod_target *origin)
1518 {
1519 struct bpf_diag_history_event event = {
1520 .insn_idx = insn_idx,
1521 .kind = BPF_DIAG_HISTORY_MOD,
1522 .mod = {
1523 .target = target,
1524 .reason = reason,
1525 },
1526 };
1527
1528 if (old_reg)
1529 diag_snapshot_reg(&event.mod.old, old_reg);
1530 if (new_reg)
1531 diag_snapshot_reg(&event.mod.new, new_reg);
1532 if (origin) {
1533 event.mod.origin = *origin;
1534 event.mod.origin_valid = true;
1535 } else if (diag_mod_insn_origin(env, insn_idx, &target, &event.mod.origin)) {
1536 event.mod.origin_valid = true;
1537 }
1538 if (old_reg && new_reg &&
1539 (reason == BPF_DIAG_MOD_WRITE || reason == BPF_DIAG_MOD_SPILL) &&
1540 !memcmp(&event.mod.old, &event.mod.new, sizeof(event.mod.old)) &&
1541 !event.mod.origin_valid &&
1542 diag_mod_keeps_lineage(env, &event))
1543 return;
1544
1545 diag_append_history(env, &event);
1546 }
1547
target_to_reg(struct bpf_verifier_env * env,const struct bpf_diag_mod_target * target)1548 static struct bpf_reg_state *target_to_reg(struct bpf_verifier_env *env,
1549 const struct bpf_diag_mod_target *target)
1550 {
1551 struct bpf_verifier_state *vstate = env->cur_state;
1552 struct bpf_func_state *state;
1553
1554 state = target->frameno <= vstate->curframe ? vstate->frame[target->frameno] : NULL;
1555
1556 if (!state)
1557 return NULL;
1558 if (state->diag_frame_id != target->frame_id)
1559 return NULL;
1560
1561 switch (target->kind) {
1562 case BPF_DIAG_MOD_TARGET_REG:
1563 if (target->regno >= MAX_BPF_REG)
1564 return NULL;
1565 return &state->regs[target->regno];
1566 case BPF_DIAG_MOD_TARGET_STACK_ARG:
1567 if (target->stack_arg >= state->out_stack_arg_cnt)
1568 return NULL;
1569 return &state->stack_arg_regs[target->stack_arg];
1570 case BPF_DIAG_MOD_TARGET_STACK_SLOT:
1571 if (target->spi >= state->allocated_stack / BPF_REG_SIZE)
1572 return NULL;
1573 return &state->stack[target->spi].spilled_ptr;
1574 default:
1575 return NULL;
1576 }
1577 }
1578
reg_to_target(struct bpf_verifier_env * env,const struct bpf_reg_state * reg,struct bpf_diag_mod_target * target)1579 static bool reg_to_target(struct bpf_verifier_env *env, const struct bpf_reg_state *reg,
1580 struct bpf_diag_mod_target *target)
1581 {
1582 struct bpf_verifier_state *vstate = env->cur_state;
1583 unsigned long addr = (unsigned long)reg;
1584 int frame;
1585
1586 for (frame = 0; frame <= vstate->curframe; frame++) {
1587 struct bpf_func_state *state = vstate->frame[frame];
1588 unsigned long start, end;
1589 u32 nslots = state->allocated_stack / BPF_REG_SIZE;
1590 int spi;
1591
1592 start = (unsigned long)state->regs;
1593 end = (unsigned long)(state->regs + MAX_BPF_REG);
1594 if (addr >= start && addr < end) {
1595 *target = diag_reg_target(state->diag_frame_id, state->frameno,
1596 reg - state->regs);
1597 return true;
1598 }
1599
1600 start = (unsigned long)state->stack_arg_regs;
1601 end = (unsigned long)(state->stack_arg_regs + state->out_stack_arg_cnt);
1602 if (state->out_stack_arg_cnt && addr >= start && addr < end) {
1603 *target = diag_stack_arg_target(state->diag_frame_id, state->frameno,
1604 reg - state->stack_arg_regs);
1605 return true;
1606 }
1607
1608 start = (unsigned long)state->stack;
1609 end = (unsigned long)(state->stack + nslots);
1610 if (nslots && addr >= start && addr < end) {
1611 spi = ((const char *)reg - (const char *)state->stack) /
1612 sizeof(*state->stack);
1613 *target = diag_stack_slot_target(state->diag_frame_id, state->frameno, spi);
1614 return true;
1615 }
1616 }
1617 return false;
1618 }
1619
bpf_diag_mod_begin(struct bpf_verifier_env * env,const struct bpf_reg_state * reg,const struct bpf_reg_state * origin,enum bpf_diag_mod_reason reason)1620 void bpf_diag_mod_begin(struct bpf_verifier_env *env, const struct bpf_reg_state *reg,
1621 const struct bpf_reg_state *origin, enum bpf_diag_mod_reason reason)
1622 {
1623 struct bpf_diag *diag = env->diag;
1624
1625 if (!diag)
1626 return;
1627 diag->mod.active = reg_to_target(env, reg, &diag->mod.target);
1628 if (!diag->mod.active)
1629 return;
1630 diag->mod.target_reg_snapshot = *reg;
1631 diag->mod.insn_idx = env->insn_idx;
1632 diag->mod.reason = reason;
1633 diag->mod.origin_valid = origin && reg_to_target(env, origin, &diag->mod.origin);
1634 }
1635
bpf_diag_mod_end(struct bpf_verifier_env * env)1636 void bpf_diag_mod_end(struct bpf_verifier_env *env)
1637 {
1638 struct bpf_diag *diag = env->diag;
1639 const struct bpf_reg_state *new_reg;
1640
1641 if (!diag || !diag->mod.active)
1642 return;
1643 diag->mod.active = false;
1644 /*
1645 * Resolve the target again because the enclosing function state's stack
1646 * may have been reallocated while the modification was in progress.
1647 */
1648 new_reg = target_to_reg(env, &diag->mod.target);
1649 if (!new_reg)
1650 return;
1651 diag_record_mod(env, diag->mod.insn_idx, diag->mod.target, diag->mod.reason,
1652 &diag->mod.target_reg_snapshot, new_reg,
1653 diag->mod.origin_valid ? &diag->mod.origin : NULL);
1654 }
1655
bpf_diag_record_scrub(struct bpf_verifier_env * env,const struct bpf_reg_state * reg,enum bpf_diag_mod_reason reason)1656 void bpf_diag_record_scrub(struct bpf_verifier_env *env, const struct bpf_reg_state *reg,
1657 enum bpf_diag_mod_reason reason)
1658 {
1659 struct bpf_diag_mod_target target;
1660
1661 if (!env->diag || reg->type == NOT_INIT || !reg_to_target(env, reg, &target))
1662 return;
1663 diag_record_mod(env, env->insn_idx, target, reason, reg, NULL, NULL);
1664 }
1665
bpf_diag_record_scrub_stack(struct bpf_verifier_env * env,const struct bpf_func_state * state,s16 min_off,s16 max_off,enum bpf_diag_mod_reason reason)1666 void bpf_diag_record_scrub_stack(struct bpf_verifier_env *env,
1667 const struct bpf_func_state *state, s16 min_off, s16 max_off,
1668 enum bpf_diag_mod_reason reason)
1669 {
1670 diag_record_mod(env, env->insn_idx,
1671 diag_stack_range_target(state->diag_frame_id, state->frameno, min_off, max_off),
1672 reason, NULL, NULL, NULL);
1673 }
1674
diag_record_ref(struct bpf_verifier_env * env,u32 insn_idx,u8 kind,u32 ref_id)1675 static void diag_record_ref(struct bpf_verifier_env *env, u32 insn_idx, u8 kind, u32 ref_id)
1676 {
1677 struct bpf_diag_history_event event = {
1678 .insn_idx = insn_idx,
1679 .kind = kind,
1680 .ref = {
1681 .ref_id = ref_id,
1682 },
1683 };
1684
1685 diag_append_history(env, &event);
1686 }
1687
bpf_diag_record_ref_acquire(struct bpf_verifier_env * env,u32 insn_idx,u32 ref_id)1688 void bpf_diag_record_ref_acquire(struct bpf_verifier_env *env, u32 insn_idx, u32 ref_id)
1689 {
1690 diag_record_ref(env, insn_idx, BPF_DIAG_HISTORY_REF_ACQUIRE, ref_id);
1691 }
1692
bpf_diag_record_ref_release(struct bpf_verifier_env * env,u32 insn_idx,u32 ref_id)1693 void bpf_diag_record_ref_release(struct bpf_verifier_env *env, u32 insn_idx, u32 ref_id)
1694 {
1695 diag_record_ref(env, insn_idx, BPF_DIAG_HISTORY_REF_RELEASE, ref_id);
1696 }
1697
bpf_diag_record_context(struct bpf_verifier_env * env,u32 insn_idx,enum bpf_diag_context_kind ctx_kind,bool enter,u32 depth)1698 void bpf_diag_record_context(struct bpf_verifier_env *env, u32 insn_idx,
1699 enum bpf_diag_context_kind ctx_kind, bool enter, u32 depth)
1700 {
1701 /*
1702 * Keep leave events so context rendering can stop at a depth-zero exit
1703 * and show nested-region depth accurately for the active path.
1704 */
1705 struct bpf_diag_history_event event = {
1706 .insn_idx = insn_idx,
1707 .kind = BPF_DIAG_HISTORY_CONTEXT,
1708 .ctx = {
1709 .kind = ctx_kind,
1710 .enter = enter,
1711 .depth = depth,
1712 },
1713 };
1714
1715 diag_append_history(env, &event);
1716 }
1717
diag_history_context_start_idx(const struct bpf_diag_log * log,const struct bpf_diag_history_opts * opts)1718 static int diag_history_context_start_idx(const struct bpf_diag_log *log,
1719 const struct bpf_diag_history_opts *opts)
1720 {
1721 int i;
1722
1723 if (!opts->ctx_depth)
1724 return 0;
1725
1726 /* Find the most recent outermost entry, or a depth-zero exit. */
1727 for (i = log->cnt; i > 0; i--) {
1728 const struct bpf_diag_history_event *event;
1729
1730 event = &log->events[log_pos(log, i - 1)];
1731
1732 if (event->kind != BPF_DIAG_HISTORY_CONTEXT || event->ctx.kind != opts->ctx_kind)
1733 continue;
1734
1735 if (event->ctx.enter && event->ctx.depth == 1)
1736 return i - 1;
1737 if (!event->ctx.enter && event->ctx.depth == 0)
1738 return 0;
1739 }
1740
1741 return 0;
1742 }
1743
1744 struct bpf_diag_history_filter {
1745 const struct bpf_diag_history_opts *opts;
1746 u32 lineage_start;
1747 bool lineage_valid;
1748 };
1749
diag_target_matches(const struct bpf_diag_mod_target * event_target,const struct bpf_diag_mod_target * target)1750 static bool diag_target_matches(const struct bpf_diag_mod_target *event_target,
1751 const struct bpf_diag_mod_target *target)
1752 {
1753 int slot_off;
1754
1755 if (event_target->frame_id != target->frame_id || event_target->frameno != target->frameno)
1756 return false;
1757
1758 if (event_target->kind == BPF_DIAG_MOD_TARGET_STACK_RANGE &&
1759 target->kind == BPF_DIAG_MOD_TARGET_STACK_SLOT) {
1760 slot_off = -(target->spi + 1) * BPF_REG_SIZE;
1761 return event_target->range.min_off < slot_off + BPF_REG_SIZE &&
1762 event_target->range.max_off > slot_off;
1763 }
1764
1765 if (event_target->kind != target->kind)
1766 return false;
1767
1768 switch (target->kind) {
1769 case BPF_DIAG_MOD_TARGET_REG:
1770 return event_target->regno == target->regno;
1771 case BPF_DIAG_MOD_TARGET_STACK_ARG:
1772 return event_target->stack_arg == target->stack_arg;
1773 case BPF_DIAG_MOD_TARGET_STACK_SLOT:
1774 return event_target->spi == target->spi;
1775 default:
1776 return false;
1777 }
1778 }
1779
diag_build_lineage(struct bpf_verifier_env * env,struct bpf_diag_log * log,struct bpf_diag_history_filter * filter)1780 static void diag_build_lineage(struct bpf_verifier_env *env, struct bpf_diag_log *log,
1781 struct bpf_diag_history_filter *filter)
1782 {
1783 const struct bpf_diag_history_opts *opts = filter->opts;
1784 struct bpf_diag_mod_target target;
1785 int i;
1786
1787 for (i = 0; i < log->cnt; i++)
1788 log->events[log_pos(log, i)].in_lineage = false;
1789
1790 if (opts->scope == BPF_DIAG_HISTORY_SCOPE_REG)
1791 target = diag_reg_target(opts->frame_id, opts->frameno, opts->regno);
1792 else if (opts->scope == BPF_DIAG_HISTORY_SCOPE_STACK_ARG)
1793 target = diag_stack_arg_target(opts->frame_id, opts->frameno,
1794 opts->stack_arg_slot);
1795 else
1796 return;
1797
1798 /*
1799 * Find the nearest mutation of the active target. A fill or spill changes
1800 * the target to its origin, so the same walk follows register/stack
1801 * lineage recursively until it reaches the write that created the value.
1802 */
1803 for (i = log->cnt; i > 0; i--) {
1804 struct bpf_diag_history_event *event;
1805
1806 event = &log->events[log_pos(log, i - 1)];
1807 if (event->kind != BPF_DIAG_HISTORY_MOD ||
1808 !diag_target_matches(&event->mod.target, &target))
1809 continue;
1810
1811 event->in_lineage = true;
1812 filter->lineage_start = i - 1;
1813 filter->lineage_valid = true;
1814
1815 if (event->mod.origin_valid) {
1816 target = event->mod.origin;
1817 continue;
1818 }
1819 if (event->mod.reason != BPF_DIAG_MOD_WRITE &&
1820 event->mod.reason != BPF_DIAG_MOD_SPILL)
1821 continue;
1822 if (diag_mod_keeps_lineage(env, event))
1823 continue;
1824 break;
1825 }
1826 }
1827
diag_history_start_idx(const struct bpf_diag_log * log,const struct bpf_diag_history_filter * filter)1828 static int diag_history_start_idx(const struct bpf_diag_log *log,
1829 const struct bpf_diag_history_filter *filter)
1830 {
1831 const struct bpf_diag_history_opts *opts = filter->opts;
1832 int i;
1833
1834 if (opts->scope == BPF_DIAG_HISTORY_SCOPE_CONTEXT)
1835 return diag_history_context_start_idx(log, opts);
1836 if (filter->lineage_valid)
1837 return filter->lineage_start;
1838 if (opts->scope != BPF_DIAG_HISTORY_SCOPE_REF)
1839 return 0;
1840
1841 for (i = log->cnt; i > 0; i--) {
1842 const struct bpf_diag_history_event *event;
1843
1844 event = &log->events[log_pos(log, i - 1)];
1845 if (event->kind == BPF_DIAG_HISTORY_REF_ACQUIRE &&
1846 event->ref.ref_id == opts->ref_id)
1847 return i - 1;
1848 }
1849
1850 return 0;
1851 }
1852
diag_history_event_visible(const struct bpf_diag_history_event * event,const struct bpf_diag_history_filter * filter)1853 static bool diag_history_event_visible(const struct bpf_diag_history_event *event,
1854 const struct bpf_diag_history_filter *filter)
1855 {
1856 const struct bpf_diag_history_opts *opts = filter->opts;
1857
1858 switch (event->kind) {
1859 case BPF_DIAG_HISTORY_BRANCH:
1860 return true;
1861 case BPF_DIAG_HISTORY_MOD:
1862 return filter->lineage_valid && event->in_lineage;
1863 case BPF_DIAG_HISTORY_REF_ACQUIRE:
1864 case BPF_DIAG_HISTORY_REF_RELEASE:
1865 return opts->scope == BPF_DIAG_HISTORY_SCOPE_REF &&
1866 event->ref.ref_id == opts->ref_id;
1867 case BPF_DIAG_HISTORY_CONTEXT:
1868 return opts->scope == BPF_DIAG_HISTORY_SCOPE_CONTEXT &&
1869 event->ctx.kind == opts->ctx_kind;
1870 default:
1871 return false;
1872 }
1873 }
1874
diag_s64_bound_name(s64 value)1875 static const char *diag_s64_bound_name(s64 value)
1876 {
1877 if (value == S64_MIN)
1878 return "S64_MIN";
1879 if (value == S64_MAX)
1880 return "S64_MAX";
1881 return NULL;
1882 }
1883
diag_u64_bound_name(u64 value)1884 static const char *diag_u64_bound_name(u64 value)
1885 {
1886 if (value == U64_MAX)
1887 return "U64_MAX";
1888 return NULL;
1889 }
1890
diag_s64_str(struct bpf_verifier_env * env,s64 value)1891 static const char *diag_s64_str(struct bpf_verifier_env *env, s64 value)
1892 {
1893 return diag_s64_bound_name(value) ?: bpf_diag_fmt(env, "%lld", value);
1894 }
1895
diag_u64_str(struct bpf_verifier_env * env,u64 value)1896 static const char *diag_u64_str(struct bpf_verifier_env *env, u64 value)
1897 {
1898 return diag_u64_bound_name(value) ?: bpf_diag_fmt(env, "%llu", value);
1899 }
1900
diag_cnum64_unknown(struct cnum64 range)1901 static bool diag_cnum64_unknown(struct cnum64 range)
1902 {
1903 return cnum64_smin(range) == S64_MIN && cnum64_smax(range) == S64_MAX &&
1904 cnum64_umin(range) == 0 && cnum64_umax(range) == U64_MAX;
1905 }
1906
diag_snapshot_unknown(const struct bpf_diag_reg_snapshot * snapshot)1907 static bool diag_snapshot_unknown(const struct bpf_diag_reg_snapshot *snapshot)
1908 {
1909 return tnum_is_unknown(snapshot->var_off) && diag_cnum64_unknown(snapshot->r64);
1910 }
1911
diag_scalar_range(struct bpf_verifier_env * env,struct cnum64 range)1912 static const char *diag_scalar_range(struct bpf_verifier_env *env, struct cnum64 range)
1913 {
1914 return bpf_diag_fmt(env, "signed range [%s, %s], unsigned range [%s, %s]",
1915 diag_s64_str(env, cnum64_smin(range)),
1916 diag_s64_str(env, cnum64_smax(range)),
1917 diag_u64_str(env, cnum64_umin(range)),
1918 diag_u64_str(env, cnum64_umax(range)));
1919 }
1920
bpf_diag_fmt_s64_sum(struct bpf_verifier_env * env,s64 value,int addend)1921 const char *bpf_diag_fmt_s64_sum(struct bpf_verifier_env *env, s64 value, int addend)
1922 {
1923 s64 sum;
1924
1925 if (check_add_overflow(value, (s64)addend, &sum))
1926 return bpf_diag_fmt(env, "%lld plus %d (%s)", value, addend,
1927 addend < 0 ? "below S64_MIN" : "above S64_MAX");
1928
1929 return bpf_diag_fmt(env, "%lld", sum);
1930 }
1931
diag_access_offset(struct bpf_verifier_env * env,int off,const struct bpf_reg_state * reg)1932 static const char *diag_access_offset(struct bpf_verifier_env *env, int off,
1933 const struct bpf_reg_state *reg)
1934 {
1935 if (tnum_is_const(reg->var_off))
1936 return bpf_diag_fmt(env, "constant %s",
1937 bpf_diag_fmt_s64_sum(env, (s64)reg->var_off.value, off));
1938
1939 if (tnum_is_unknown(reg->var_off) && diag_cnum64_unknown(reg->r64))
1940 return bpf_diag_fmt(env, "unbounded");
1941
1942 if (off)
1943 return bpf_diag_fmt(env,
1944 "variable: known bits %#llx, unknown mask %#llx, plus fixed offset %d; %s",
1945 (u64)reg->var_off.value, reg->var_off.mask, off,
1946 diag_scalar_range(env, reg->r64));
1947 return bpf_diag_fmt(env, "variable: known bits %#llx, unknown mask %#llx; %s",
1948 (u64)reg->var_off.value, reg->var_off.mask,
1949 diag_scalar_range(env, reg->r64));
1950 }
1951
bpf_diag_mem_bounds(struct bpf_verifier_env * env,u32 insn_idx,int regno,const char * reg_name,const char * type_name,const char * proof,int off,int size,u32 mem_size,const struct bpf_reg_state * reg)1952 void bpf_diag_mem_bounds(struct bpf_verifier_env *env, u32 insn_idx, int regno,
1953 const char *reg_name, const char *type_name, const char *proof,
1954 int off, int size, u32 mem_size, const struct bpf_reg_state *reg)
1955 {
1956 const struct bpf_func_state *frame = diag_current_frame(env);
1957 struct bpf_diag_history_opts opts = {
1958 .scope = BPF_DIAG_HISTORY_SCOPE_REG,
1959 .frame_id = frame->diag_frame_id,
1960 .frameno = frame->frameno,
1961 .regno = regno,
1962 };
1963 const char *offset_desc;
1964
1965 if (!bpf_diag_enabled(env))
1966 return;
1967
1968 offset_desc = diag_access_offset(env, off, reg);
1969
1970 bpf_diag_header(env, MEMORY_SAFETY, "access outside bounds");
1971 diag_reason(
1972 env, "The verifier cannot prove offset + access_size <= object_size. Here, %s. %s is %s; offset is %s; access_size is %d; object_size is %u.",
1973 proof, reg_name, type_name, offset_desc, size, mem_size);
1974
1975 diag_section(env, "At");
1976 bpf_diag_source(env, insn_idx, "error", "access may be outside object bounds");
1977
1978 if (regno >= 0)
1979 diag_print_history(env, &opts);
1980
1981 diag_suggestion(
1982 env, "Add or adjust a bounds check that proves offset + access_size stays within the object.");
1983 }
1984
diag_lock_name(const struct bpf_reference_state * lock)1985 static const char *diag_lock_name(const struct bpf_reference_state *lock)
1986 {
1987 switch (lock->type) {
1988 case REF_TYPE_LOCK:
1989 return "bpf_spin_lock";
1990 case REF_TYPE_RES_LOCK:
1991 return "resource spin lock";
1992 case REF_TYPE_RES_LOCK_IRQ:
1993 return "IRQ-saving resource spin lock";
1994 default:
1995 return "lock";
1996 }
1997 }
1998
diag_res_report(struct bpf_verifier_env * env,u32 insn_idx,const char * problem,const char * reason)1999 static void diag_res_report(struct bpf_verifier_env *env, u32 insn_idx, const char *problem,
2000 const char *reason)
2001 {
2002 bpf_diag_header(env, RESOURCE_LIFETIME_SAFETY, problem);
2003 diag_reason(env, "%s", reason);
2004
2005 diag_section(env, "At");
2006 bpf_diag_source(env, insn_idx, "error", "%s", problem);
2007 }
2008
bpf_diag_res(struct bpf_verifier_env * env,u32 insn_idx,const char * problem,const char * reason,const char * suggestion)2009 void bpf_diag_res(struct bpf_verifier_env *env, u32 insn_idx, const char *problem,
2010 const char *reason, const char *suggestion)
2011 {
2012 diag_res_report(env, insn_idx, problem, reason);
2013 diag_suggestion(env, "%s", suggestion);
2014 }
2015
bpf_diag_lock(struct bpf_verifier_env * env,u32 insn_idx,const char * problem,const char * reason,const char * suggestion,const struct bpf_reference_state * active_lock)2016 void bpf_diag_lock(struct bpf_verifier_env *env, u32 insn_idx, const char *problem,
2017 const char *reason, const char *suggestion,
2018 const struct bpf_reference_state *active_lock)
2019 {
2020 diag_res_report(env, insn_idx, problem, reason);
2021
2022 if (active_lock) {
2023 diag_section(env, "Active lock");
2024 bpf_diag_source(env, active_lock->insn_idx, "acquired",
2025 "active %s has verifier identity %d",
2026 diag_lock_name(active_lock), active_lock->id);
2027 }
2028
2029 diag_suggestion(env, "%s", suggestion);
2030 }
2031
bpf_diag_irq(struct bpf_verifier_env * env,u32 insn_idx,const char * problem,const char * reason,const char * suggestion,u32 depth)2032 void bpf_diag_irq(struct bpf_verifier_env *env, u32 insn_idx, const char *problem,
2033 const char *reason, const char *suggestion, u32 depth)
2034 {
2035 struct bpf_diag_history_opts opts = {
2036 .scope = BPF_DIAG_HISTORY_SCOPE_CONTEXT,
2037 .ctx_kind = BPF_DIAG_CONTEXT_IRQ,
2038 .ctx_depth = depth,
2039 };
2040
2041 bpf_diag_header(env, RESOURCE_LIFETIME_SAFETY, problem);
2042 diag_reason(env, "%s", reason);
2043
2044 diag_section(env, "At");
2045 bpf_diag_source(env, insn_idx, "error", "%s", problem);
2046
2047 if (depth)
2048 diag_print_history(env, &opts);
2049
2050 diag_suggestion(env, "%s", suggestion);
2051 }
2052
bpf_diag_leak(struct bpf_verifier_env * env,u32 ref_id,u32 alloc_insn,u32 fail_insn)2053 void bpf_diag_leak(struct bpf_verifier_env *env, u32 ref_id, u32 alloc_insn, u32 fail_insn)
2054 {
2055 struct bpf_diag_history_opts opts = {
2056 .scope = BPF_DIAG_HISTORY_SCOPE_REF,
2057 .ref_id = ref_id,
2058 };
2059
2060 bpf_diag_header(env, RESOURCE_LIFETIME_SAFETY, "unreleased resource");
2061 diag_reason(
2062 env, "Owned resource (id=%u) was acquired at instruction %u and still needs to be released before this exit path.",
2063 ref_id, alloc_insn);
2064
2065 diag_section(env, "At");
2066 bpf_diag_source(env, fail_insn, "error",
2067 "owned resource (id=%u) still needs release", ref_id);
2068
2069 diag_print_history(env, &opts);
2070
2071 diag_suggestion(
2072 env, "Release or transfer ownership of the acquired resource on every path before the program exits.");
2073 }
2074
diag_var_offset(struct bpf_verifier_env * env,const struct bpf_diag_reg_snapshot * snapshot)2075 static const char *diag_var_offset(struct bpf_verifier_env *env,
2076 const struct bpf_diag_reg_snapshot *snapshot)
2077 {
2078 if (tnum_is_const(snapshot->var_off))
2079 return bpf_diag_fmt(env, "at offset %lld", (s64)snapshot->var_off.value);
2080
2081 if (diag_snapshot_unknown(snapshot))
2082 return bpf_diag_fmt(env, "with unknown offset");
2083
2084 return bpf_diag_fmt(env,
2085 "with variable offset: known bits %#llx, unknown mask %#llx, %s",
2086 snapshot->var_off.value, snapshot->var_off.mask,
2087 diag_scalar_range(env, snapshot->r64));
2088 }
2089
diag_reg_map_name(const struct bpf_map * map)2090 static const char *diag_reg_map_name(const struct bpf_map *map)
2091 {
2092 if (!map || !map->name[0])
2093 return NULL;
2094
2095 return map->name;
2096 }
2097
diag_reg_snapshot(struct bpf_verifier_env * env,const struct bpf_diag_reg_snapshot * snapshot)2098 static const char *diag_reg_snapshot(struct bpf_verifier_env *env,
2099 const struct bpf_diag_reg_snapshot *snapshot)
2100 {
2101 const char *type_name = reg_type_str(env, snapshot->type);
2102 const char *offset = diag_var_offset(env, snapshot);
2103 const char *btf = snapshot->btf && snapshot->btf_id ?
2104 bpf_diag_fmt_btf_type(env, snapshot->btf, snapshot->btf_id) : NULL;
2105 const char *map_name;
2106
2107 if (snapshot->type == SCALAR_VALUE) {
2108 if (tnum_is_const(snapshot->var_off))
2109 return bpf_diag_fmt(env, "integer scalar value %lld",
2110 (s64)snapshot->var_off.value);
2111 if (diag_snapshot_unknown(snapshot))
2112 return bpf_diag_fmt(env, "integer scalar with unknown value");
2113 if (cnum64_is_const(snapshot->r64))
2114 return bpf_diag_fmt(env, "integer scalar value %lld",
2115 cnum64_smin(snapshot->r64));
2116 return bpf_diag_fmt(env, "integer scalar with %s",
2117 diag_scalar_range(env, snapshot->r64));
2118 }
2119
2120 if (snapshot->type == NOT_INIT)
2121 return bpf_diag_fmt(env, "uninitialized value");
2122
2123 if (base_type(snapshot->type) == PTR_TO_CTX)
2124 return bpf_diag_fmt(env, "context pointer %s", offset);
2125
2126 if (base_type(snapshot->type) == PTR_TO_STACK)
2127 return bpf_diag_fmt(env, "stack pointer %s", offset);
2128
2129 if (base_type(snapshot->type) == PTR_TO_MAP_VALUE) {
2130 const char *kind = type_may_be_null(snapshot->type) ? "nullable map value" :
2131 "map value";
2132
2133 map_name = diag_reg_map_name(snapshot->map_ptr);
2134 if (map_name)
2135 return bpf_diag_fmt(env, "%s from %s %s", kind, map_name, offset);
2136 return bpf_diag_fmt(env, "%s %s", kind, offset);
2137 }
2138
2139 if (base_type(snapshot->type) == CONST_PTR_TO_MAP) {
2140 map_name = diag_reg_map_name(snapshot->map_ptr);
2141 if (map_name)
2142 return bpf_diag_fmt(env, "map pointer for map %s", map_name);
2143 return bpf_diag_fmt(env, "map pointer");
2144 }
2145
2146 if (type_is_non_owning_ref(snapshot->type)) {
2147 if (btf)
2148 return bpf_diag_fmt(env, "borrowed allocated object pointer type=%s", btf);
2149 return bpf_diag_fmt(env, "borrowed allocated object pointer");
2150 }
2151
2152 if (type_is_ptr_alloc_obj(snapshot->type)) {
2153 if (btf)
2154 return bpf_diag_fmt(env, "owned allocated object pointer type=%s", btf);
2155 return bpf_diag_fmt(env, "owned allocated object pointer");
2156 }
2157
2158 if (base_type(snapshot->type) == PTR_TO_BTF_ID && btf)
2159 return bpf_diag_fmt(env, "%s type=%s %s", type_name, btf, offset);
2160
2161 return bpf_diag_fmt(env, "%s %s", type_name, offset);
2162 }
2163
diag_mod_target_desc(struct bpf_verifier_env * env,const struct bpf_diag_mod_target * target)2164 static const char *diag_mod_target_desc(struct bpf_verifier_env *env,
2165 const struct bpf_diag_mod_target *target)
2166 {
2167 switch (target->kind) {
2168 case BPF_DIAG_MOD_TARGET_REG:
2169 return bpf_diag_fmt(env, "R%u", target->regno);
2170 case BPF_DIAG_MOD_TARGET_STACK_ARG:
2171 return bpf_diag_fmt(env, "*(R11-%u)", (target->stack_arg + 1) * BPF_REG_SIZE);
2172 case BPF_DIAG_MOD_TARGET_STACK_SLOT:
2173 return bpf_diag_fmt(env, "stack slot fp%d", -(target->spi + 1) * BPF_REG_SIZE);
2174 default:
2175 return "value";
2176 }
2177 }
2178
diag_print_mod(struct bpf_verifier_env * env,const struct bpf_diag_history_event * event)2179 static void diag_print_mod(struct bpf_verifier_env *env, const struct bpf_diag_history_event *event)
2180 {
2181 const struct bpf_diag_mod_target *target = &event->mod.target;
2182 const char *target_desc, *reason = NULL, *old, *new;
2183 const char *label = "update";
2184
2185 if (target->kind == BPF_DIAG_MOD_TARGET_STACK_RANGE) {
2186 bpf_diag_source(
2187 env, event->insn_idx, "invalidated",
2188 "variable-offset stack write may affect bytes fp%d through fp%d",
2189 target->range.min_off, target->range.max_off - 1);
2190 return;
2191 }
2192
2193 old = diag_reg_snapshot(env, &event->mod.old);
2194 new = diag_reg_snapshot(env, &event->mod.new);
2195 target_desc = diag_mod_target_desc(env, target);
2196
2197 switch (event->mod.reason) {
2198 case BPF_DIAG_MOD_REF_RELEASE:
2199 reason = target->kind == BPF_DIAG_MOD_TARGET_REG ? "resource release invalidated "
2200 "this pointer" :
2201 "resource release invalidated "
2202 "this value";
2203 break;
2204 case BPF_DIAG_MOD_PKT_DATA_CHANGE:
2205 reason = "packet data may have moved";
2206 break;
2207 case BPF_DIAG_MOD_NON_OWN_REF:
2208 reason = "leaving the protected region invalidated this borrowed pointer";
2209 break;
2210 case BPF_DIAG_MOD_CALLER_SAVED:
2211 reason = target->kind == BPF_DIAG_MOD_TARGET_STACK_ARG ?
2212 "call invalidated this outgoing stack argument" :
2213 "call invalidated this caller-saved register";
2214 break;
2215 case BPF_DIAG_MOD_WRITE:
2216 if (target->kind == BPF_DIAG_MOD_TARGET_STACK_SLOT)
2217 reason = "a later stack write overwrote this spilled value";
2218 break;
2219 case BPF_DIAG_MOD_SPILL:
2220 label = "spilled";
2221 break;
2222 case BPF_DIAG_MOD_VAR_WRITE:
2223 default:
2224 break;
2225 }
2226
2227 if (reason) {
2228 bpf_diag_source(env, event->insn_idx, "invalidated",
2229 "%s: %s; previous value was %s", target_desc, reason, old);
2230 return;
2231 }
2232
2233 bpf_diag_source(env, event->insn_idx, label, "%s changed from %s to %s", target_desc,
2234 old, new);
2235 }
2236
diag_print_ref_event(struct bpf_verifier_env * env,const struct bpf_diag_history_event * event)2237 static void diag_print_ref_event(struct bpf_verifier_env *env,
2238 const struct bpf_diag_history_event *event)
2239 {
2240 const char *label;
2241
2242 label = event->kind == BPF_DIAG_HISTORY_REF_ACQUIRE ? "acquired" : "released";
2243 bpf_diag_source(env, event->insn_idx, label, "owned resource (id=%u)",
2244 event->ref.ref_id);
2245 }
2246
diag_context_name(enum bpf_diag_context_kind kind)2247 static const char *diag_context_name(enum bpf_diag_context_kind kind)
2248 {
2249 switch (kind) {
2250 case BPF_DIAG_CONTEXT_RCU:
2251 return "RCU read lock region";
2252 case BPF_DIAG_CONTEXT_PREEMPT:
2253 return "non-preemptible region";
2254 case BPF_DIAG_CONTEXT_IRQ:
2255 return "IRQ-disabled region";
2256 case BPF_DIAG_CONTEXT_LOCK:
2257 return "lock region";
2258 case BPF_DIAG_CONTEXT_NONE:
2259 default:
2260 return "non-sleepable program";
2261 }
2262 }
2263
diag_print_context_event(struct bpf_verifier_env * env,const struct bpf_diag_history_event * event)2264 static void diag_print_context_event(struct bpf_verifier_env *env,
2265 const struct bpf_diag_history_event *event)
2266 {
2267 bpf_diag_source(env, event->insn_idx, "context", "%s %s; depth is now %u",
2268 event->ctx.enter ? "entered" : "left",
2269 diag_context_name(event->ctx.kind), event->ctx.depth);
2270 }
2271
diag_print_history(struct bpf_verifier_env * env,const struct bpf_diag_history_opts * opts)2272 static void diag_print_history(struct bpf_verifier_env *env,
2273 const struct bpf_diag_history_opts *opts)
2274 {
2275 const struct bpf_diag_history_event *event;
2276 struct bpf_diag_history_filter filter = {
2277 .opts = opts,
2278 };
2279 struct bpf_diag_log *log;
2280 struct diag_fmt_mark mark;
2281 bool first = true;
2282 int start_idx;
2283 u32 i, visible_cnt = 0, visible_idx = 0;
2284
2285 if (!bpf_diag_enabled(env))
2286 return;
2287
2288 if (!env->diag)
2289 return;
2290 log = &env->diag->log;
2291
2292 diag_build_lineage(env, log, &filter);
2293
2294 start_idx = diag_history_start_idx(log, &filter);
2295 for (i = start_idx; i < log->cnt; i++) {
2296 event = &log->events[log_pos(log, i)];
2297 if (diag_history_event_visible(event, &filter))
2298 visible_cnt++;
2299 }
2300
2301 if (!visible_cnt && !log->first_seq && opts->scope == BPF_DIAG_HISTORY_SCOPE_STACK_ARG)
2302 return;
2303
2304 diag_section(env, "Causal path");
2305 mark = diag_fmt_save(env);
2306 for (i = start_idx; i < log->cnt; i++) {
2307 event = &log->events[log_pos(log, i)];
2308 if (!diag_history_event_visible(event, &filter))
2309 continue;
2310
2311 diag_fmt_restore(env, mark);
2312 if (visible_cnt > BPF_DIAG_HISTORY_RENDER_MAX &&
2313 visible_idx >= BPF_DIAG_HISTORY_RENDER_MAX / 2 &&
2314 visible_idx < visible_cnt - BPF_DIAG_HISTORY_RENDER_MAX / 2) {
2315 if (visible_idx++ != BPF_DIAG_HISTORY_RENDER_MAX / 2)
2316 continue;
2317 if (!first)
2318 diag_write(env, "\n");
2319 first = false;
2320 diag_write(env, " %u intermediate causal-history events omitted\n",
2321 visible_cnt - BPF_DIAG_HISTORY_RENDER_MAX);
2322 continue;
2323 }
2324 visible_idx++;
2325
2326 if (!first)
2327 diag_write(env, "\n");
2328 first = false;
2329
2330 switch (event->kind) {
2331 case BPF_DIAG_HISTORY_BRANCH:
2332 bpf_diag_source(env, event->insn_idx, "branch",
2333 "took the %s branch of this conditional, goto %s",
2334 event->branch.cond_true ? "true" : "false",
2335 event->branch.cond_true ? "followed" : "not followed");
2336 break;
2337 case BPF_DIAG_HISTORY_MOD:
2338 diag_print_mod(env, event);
2339 break;
2340 case BPF_DIAG_HISTORY_REF_ACQUIRE:
2341 case BPF_DIAG_HISTORY_REF_RELEASE:
2342 diag_print_ref_event(env, event);
2343 break;
2344 case BPF_DIAG_HISTORY_CONTEXT:
2345 diag_print_context_event(env, event);
2346 break;
2347 default:
2348 break;
2349 }
2350 }
2351
2352 if (!visible_cnt)
2353 diag_write(env, " no retained diagnostic events on this path\n");
2354 if (log->first_seq)
2355 diag_write(env, " %llu older causal-history event%s not retained because diagnostic "
2356 "event storage reached capacity\n",
2357 log->first_seq, log->first_seq == 1 ? "" : "s");
2358 diag_fmt_restore(env, mark);
2359 }
2360