tools/testing/selftests/bpf/prog_tests/verifier_log.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/prog_tests/verifier_log.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/prog_tests/verifier_log.c
Extension
.c
Size
14380 bytes
Lines
452
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!ASSERT_LT(prog_fd, 0, tag)) {
			close(prog_fd);
			return false;
		}
	} else /* !expect_err */ {
		if (!ASSERT_GT(prog_fd, 0, tag))
			return false;
	}
	if (prog_fd >= 0)
		close(prog_fd);
	return true;
}

static struct {
	/* strategically placed before others to avoid accidental modification by kernel */
	char filler[16384];
	char buf[16384];
	/* strategically placed after buf[] to catch more accidental corruptions */
	char reference[16384];
} logs;
static const struct bpf_insn *insns;
static size_t insn_cnt;

static int load_prog(struct bpf_prog_load_opts *opts, bool expect_load_error)
{
	int prog_fd;

	prog_fd = bpf_prog_load(BPF_PROG_TYPE_RAW_TRACEPOINT, "log_prog",
				"GPL", insns, insn_cnt, opts);
	check_prog_load(prog_fd, expect_load_error, "prog_load");

	return prog_fd;
}

static void verif_log_subtest(const char *name, bool expect_load_error, int log_level)
{
	LIBBPF_OPTS(bpf_prog_load_opts, opts);
	char *exp_log, prog_name[24], op_name[32];
	struct test_log_buf *skel;
	struct bpf_program *prog;
	size_t fixed_log_sz;
	__u32 log_true_sz_fixed, log_true_sz_rolling;
	int i, mode, err, prog_fd, res;

	skel = test_log_buf__open();
	if (!ASSERT_OK_PTR(skel, "skel_open"))
		return;

	bpf_object__for_each_program(prog, skel->obj) {
		if (strcmp(bpf_program__name(prog), name) == 0)
			bpf_program__set_autoload(prog, true);
		else
			bpf_program__set_autoload(prog, false);
	}

	err = test_log_buf__load(skel);
	if (!expect_load_error && !ASSERT_OK(err, "unexpected_load_failure"))
		goto cleanup;
	if (expect_load_error && !ASSERT_ERR(err, "unexpected_load_success"))
		goto cleanup;

	insns = bpf_program__insns(skel->progs.good_prog);
	insn_cnt = bpf_program__insn_cnt(skel->progs.good_prog);

	opts.log_buf = logs.reference;
	opts.log_size = sizeof(logs.reference);
	opts.log_level = log_level | 8 /* BPF_LOG_FIXED */;
	load_prog(&opts, expect_load_error);

	fixed_log_sz = strlen(logs.reference) + 1;
	if (!ASSERT_GT(fixed_log_sz, 50, "fixed_log_sz"))
		goto cleanup;
	memset(logs.reference + fixed_log_sz, 0, sizeof(logs.reference) - fixed_log_sz);

	/* validate BPF_LOG_FIXED works as verifier log used to work, that is:
	 * we get -ENOSPC and beginning of the full verifier log. This only
	 * works for log_level 2 and log_level 1 + failed program. For log
	 * level 2 we don't reset log at all. For log_level 1 + failed program
	 * we don't get to verification stats output. With log level 1
	 * for successful program  final result will be just verifier stats.
	 * But if provided too short log buf, kernel will NULL-out log->ubuf
	 * and will stop emitting further log. This means we'll never see
	 * predictable verifier stats.
	 * Long story short, we do the following -ENOSPC test only for
	 * predictable combinations.
	 */
	if (log_level >= 2 || expect_load_error) {
		opts.log_buf = logs.buf;
		opts.log_level = log_level | 8; /* fixed-length log */
		opts.log_size = 25;

Annotation

Implementation Notes