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