1b1a7a480SAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2b1a7a480SAndrii Nakryiko /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3b1a7a480SAndrii Nakryiko
4b1a7a480SAndrii Nakryiko #include <test_progs.h>
5b1a7a480SAndrii Nakryiko #include <bpf/btf.h>
6b1a7a480SAndrii Nakryiko
7b1a7a480SAndrii Nakryiko #include "test_log_buf.skel.h"
8b1a7a480SAndrii Nakryiko
9b1a7a480SAndrii Nakryiko
check_prog_load(int prog_fd,bool expect_err,const char * tag)10b1a7a480SAndrii Nakryiko static bool check_prog_load(int prog_fd, bool expect_err, const char *tag)
11b1a7a480SAndrii Nakryiko {
12b1a7a480SAndrii Nakryiko if (expect_err) {
13b1a7a480SAndrii Nakryiko if (!ASSERT_LT(prog_fd, 0, tag)) {
14b1a7a480SAndrii Nakryiko close(prog_fd);
15b1a7a480SAndrii Nakryiko return false;
16b1a7a480SAndrii Nakryiko }
17b1a7a480SAndrii Nakryiko } else /* !expect_err */ {
18b1a7a480SAndrii Nakryiko if (!ASSERT_GT(prog_fd, 0, tag))
19b1a7a480SAndrii Nakryiko return false;
20b1a7a480SAndrii Nakryiko }
2157875408SAndrii Nakryiko if (prog_fd >= 0)
2257875408SAndrii Nakryiko close(prog_fd);
23b1a7a480SAndrii Nakryiko return true;
24b1a7a480SAndrii Nakryiko }
25b1a7a480SAndrii Nakryiko
2657875408SAndrii Nakryiko static struct {
27b1a7a480SAndrii Nakryiko /* strategically placed before others to avoid accidental modification by kernel */
28b1a7a480SAndrii Nakryiko char filler[1024];
29b1a7a480SAndrii Nakryiko char buf[1024];
30b1a7a480SAndrii Nakryiko /* strategically placed after buf[] to catch more accidental corruptions */
31b1a7a480SAndrii Nakryiko char reference[1024];
32b1a7a480SAndrii Nakryiko } logs;
3357875408SAndrii Nakryiko static const struct bpf_insn *insns;
3457875408SAndrii Nakryiko static size_t insn_cnt;
3557875408SAndrii Nakryiko
load_prog(struct bpf_prog_load_opts * opts,bool expect_load_error)3657875408SAndrii Nakryiko static int load_prog(struct bpf_prog_load_opts *opts, bool expect_load_error)
3757875408SAndrii Nakryiko {
3857875408SAndrii Nakryiko int prog_fd;
3957875408SAndrii Nakryiko
4057875408SAndrii Nakryiko prog_fd = bpf_prog_load(BPF_PROG_TYPE_RAW_TRACEPOINT, "log_prog",
4157875408SAndrii Nakryiko "GPL", insns, insn_cnt, opts);
4257875408SAndrii Nakryiko check_prog_load(prog_fd, expect_load_error, "prog_load");
4357875408SAndrii Nakryiko
4457875408SAndrii Nakryiko return prog_fd;
4557875408SAndrii Nakryiko }
4657875408SAndrii Nakryiko
verif_log_subtest(const char * name,bool expect_load_error,int log_level)4757875408SAndrii Nakryiko static void verif_log_subtest(const char *name, bool expect_load_error, int log_level)
4857875408SAndrii Nakryiko {
4957875408SAndrii Nakryiko LIBBPF_OPTS(bpf_prog_load_opts, opts);
50b1a7a480SAndrii Nakryiko char *exp_log, prog_name[16], op_name[32];
51b1a7a480SAndrii Nakryiko struct test_log_buf *skel;
52b1a7a480SAndrii Nakryiko struct bpf_program *prog;
5357875408SAndrii Nakryiko size_t fixed_log_sz;
5457875408SAndrii Nakryiko __u32 log_true_sz_fixed, log_true_sz_rolling;
5557875408SAndrii Nakryiko int i, mode, err, prog_fd, res;
56b1a7a480SAndrii Nakryiko
57b1a7a480SAndrii Nakryiko skel = test_log_buf__open();
58b1a7a480SAndrii Nakryiko if (!ASSERT_OK_PTR(skel, "skel_open"))
59b1a7a480SAndrii Nakryiko return;
60b1a7a480SAndrii Nakryiko
61b1a7a480SAndrii Nakryiko bpf_object__for_each_program(prog, skel->obj) {
62b1a7a480SAndrii Nakryiko if (strcmp(bpf_program__name(prog), name) == 0)
63b1a7a480SAndrii Nakryiko bpf_program__set_autoload(prog, true);
64b1a7a480SAndrii Nakryiko else
65b1a7a480SAndrii Nakryiko bpf_program__set_autoload(prog, false);
66b1a7a480SAndrii Nakryiko }
67b1a7a480SAndrii Nakryiko
68b1a7a480SAndrii Nakryiko err = test_log_buf__load(skel);
69b1a7a480SAndrii Nakryiko if (!expect_load_error && !ASSERT_OK(err, "unexpected_load_failure"))
70b1a7a480SAndrii Nakryiko goto cleanup;
71b1a7a480SAndrii Nakryiko if (expect_load_error && !ASSERT_ERR(err, "unexpected_load_success"))
72b1a7a480SAndrii Nakryiko goto cleanup;
73b1a7a480SAndrii Nakryiko
74b1a7a480SAndrii Nakryiko insns = bpf_program__insns(skel->progs.good_prog);
75b1a7a480SAndrii Nakryiko insn_cnt = bpf_program__insn_cnt(skel->progs.good_prog);
76b1a7a480SAndrii Nakryiko
77b1a7a480SAndrii Nakryiko opts.log_buf = logs.reference;
78b1a7a480SAndrii Nakryiko opts.log_size = sizeof(logs.reference);
79b1a7a480SAndrii Nakryiko opts.log_level = log_level | 8 /* BPF_LOG_FIXED */;
8057875408SAndrii Nakryiko load_prog(&opts, expect_load_error);
81b1a7a480SAndrii Nakryiko
82b1a7a480SAndrii Nakryiko fixed_log_sz = strlen(logs.reference) + 1;
83b1a7a480SAndrii Nakryiko if (!ASSERT_GT(fixed_log_sz, 50, "fixed_log_sz"))
84b1a7a480SAndrii Nakryiko goto cleanup;
85b1a7a480SAndrii Nakryiko memset(logs.reference + fixed_log_sz, 0, sizeof(logs.reference) - fixed_log_sz);
86b1a7a480SAndrii Nakryiko
87b1a7a480SAndrii Nakryiko /* validate BPF_LOG_FIXED works as verifier log used to work, that is:
88b1a7a480SAndrii Nakryiko * we get -ENOSPC and beginning of the full verifier log. This only
89b1a7a480SAndrii Nakryiko * works for log_level 2 and log_level 1 + failed program. For log
90b1a7a480SAndrii Nakryiko * level 2 we don't reset log at all. For log_level 1 + failed program
91b1a7a480SAndrii Nakryiko * we don't get to verification stats output. With log level 1
92b1a7a480SAndrii Nakryiko * for successful program final result will be just verifier stats.
93b1a7a480SAndrii Nakryiko * But if provided too short log buf, kernel will NULL-out log->ubuf
94b1a7a480SAndrii Nakryiko * and will stop emitting further log. This means we'll never see
95b1a7a480SAndrii Nakryiko * predictable verifier stats.
96b1a7a480SAndrii Nakryiko * Long story short, we do the following -ENOSPC test only for
97b1a7a480SAndrii Nakryiko * predictable combinations.
98b1a7a480SAndrii Nakryiko */
99b1a7a480SAndrii Nakryiko if (log_level >= 2 || expect_load_error) {
100b1a7a480SAndrii Nakryiko opts.log_buf = logs.buf;
101b1a7a480SAndrii Nakryiko opts.log_level = log_level | 8; /* fixed-length log */
102b1a7a480SAndrii Nakryiko opts.log_size = 25;
103b1a7a480SAndrii Nakryiko
10457875408SAndrii Nakryiko prog_fd = bpf_prog_load(BPF_PROG_TYPE_RAW_TRACEPOINT, "log_fixed25",
105b1a7a480SAndrii Nakryiko "GPL", insns, insn_cnt, &opts);
106b1a7a480SAndrii Nakryiko if (!ASSERT_EQ(prog_fd, -ENOSPC, "unexpected_log_fixed_prog_load_result")) {
107b1a7a480SAndrii Nakryiko if (prog_fd >= 0)
108b1a7a480SAndrii Nakryiko close(prog_fd);
109b1a7a480SAndrii Nakryiko goto cleanup;
110b1a7a480SAndrii Nakryiko }
111b1a7a480SAndrii Nakryiko if (!ASSERT_EQ(strlen(logs.buf), 24, "log_fixed_25"))
112b1a7a480SAndrii Nakryiko goto cleanup;
113*5a674611SLorenz Bauer if (!ASSERT_STRNEQ(logs.buf, logs.reference, 24, "log_fixed_contents_25"))
114b1a7a480SAndrii Nakryiko goto cleanup;
115b1a7a480SAndrii Nakryiko }
116b1a7a480SAndrii Nakryiko
117b1a7a480SAndrii Nakryiko /* validate rolling verifier log logic: try all variations of log buf
118b1a7a480SAndrii Nakryiko * length to force various truncation scenarios
119b1a7a480SAndrii Nakryiko */
120b1a7a480SAndrii Nakryiko opts.log_buf = logs.buf;
121b1a7a480SAndrii Nakryiko
122b1a7a480SAndrii Nakryiko /* rotating mode, then fixed mode */
123b1a7a480SAndrii Nakryiko for (mode = 1; mode >= 0; mode--) {
124b1a7a480SAndrii Nakryiko /* prefill logs.buf with 'A's to detect any write beyond allowed length */
125b1a7a480SAndrii Nakryiko memset(logs.filler, 'A', sizeof(logs.filler));
126b1a7a480SAndrii Nakryiko logs.filler[sizeof(logs.filler) - 1] = '\0';
127b1a7a480SAndrii Nakryiko memset(logs.buf, 'A', sizeof(logs.buf));
128b1a7a480SAndrii Nakryiko logs.buf[sizeof(logs.buf) - 1] = '\0';
129b1a7a480SAndrii Nakryiko
130b1a7a480SAndrii Nakryiko for (i = 1; i < fixed_log_sz; i++) {
131b1a7a480SAndrii Nakryiko opts.log_size = i;
132b1a7a480SAndrii Nakryiko opts.log_level = log_level | (mode ? 0 : 8 /* BPF_LOG_FIXED */);
133b1a7a480SAndrii Nakryiko
134b1a7a480SAndrii Nakryiko snprintf(prog_name, sizeof(prog_name),
135b1a7a480SAndrii Nakryiko "log_%s_%d", mode ? "roll" : "fixed", i);
136b1a7a480SAndrii Nakryiko prog_fd = bpf_prog_load(BPF_PROG_TYPE_RAW_TRACEPOINT, prog_name,
137b1a7a480SAndrii Nakryiko "GPL", insns, insn_cnt, &opts);
138b1a7a480SAndrii Nakryiko
139b1a7a480SAndrii Nakryiko snprintf(op_name, sizeof(op_name),
140b1a7a480SAndrii Nakryiko "log_%s_prog_load_%d", mode ? "roll" : "fixed", i);
141b1a7a480SAndrii Nakryiko if (!ASSERT_EQ(prog_fd, -ENOSPC, op_name)) {
142b1a7a480SAndrii Nakryiko if (prog_fd >= 0)
143b1a7a480SAndrii Nakryiko close(prog_fd);
144b1a7a480SAndrii Nakryiko goto cleanup;
145b1a7a480SAndrii Nakryiko }
146b1a7a480SAndrii Nakryiko
147b1a7a480SAndrii Nakryiko snprintf(op_name, sizeof(op_name),
148b1a7a480SAndrii Nakryiko "log_%s_strlen_%d", mode ? "roll" : "fixed", i);
149b1a7a480SAndrii Nakryiko ASSERT_EQ(strlen(logs.buf), i - 1, op_name);
150b1a7a480SAndrii Nakryiko
151b1a7a480SAndrii Nakryiko if (mode)
152b1a7a480SAndrii Nakryiko exp_log = logs.reference + fixed_log_sz - i;
153b1a7a480SAndrii Nakryiko else
154b1a7a480SAndrii Nakryiko exp_log = logs.reference;
155b1a7a480SAndrii Nakryiko
156b1a7a480SAndrii Nakryiko snprintf(op_name, sizeof(op_name),
157b1a7a480SAndrii Nakryiko "log_%s_contents_%d", mode ? "roll" : "fixed", i);
158b1a7a480SAndrii Nakryiko if (!ASSERT_STRNEQ(logs.buf, exp_log, i - 1, op_name)) {
159b1a7a480SAndrii Nakryiko printf("CMP:%d\nS1:'%s'\nS2:'%s'\n",
160b1a7a480SAndrii Nakryiko strncmp(logs.buf, exp_log, i - 1),
161b1a7a480SAndrii Nakryiko logs.buf, exp_log);
162b1a7a480SAndrii Nakryiko goto cleanup;
163b1a7a480SAndrii Nakryiko }
164b1a7a480SAndrii Nakryiko
165b1a7a480SAndrii Nakryiko /* check that unused portions of logs.buf is not overwritten */
166b1a7a480SAndrii Nakryiko snprintf(op_name, sizeof(op_name),
167b1a7a480SAndrii Nakryiko "log_%s_unused_%d", mode ? "roll" : "fixed", i);
168b1a7a480SAndrii Nakryiko if (!ASSERT_STREQ(logs.buf + i, logs.filler + i, op_name)) {
169b1a7a480SAndrii Nakryiko printf("CMP:%d\nS1:'%s'\nS2:'%s'\n",
170b1a7a480SAndrii Nakryiko strcmp(logs.buf + i, logs.filler + i),
171b1a7a480SAndrii Nakryiko logs.buf + i, logs.filler + i);
172b1a7a480SAndrii Nakryiko goto cleanup;
173b1a7a480SAndrii Nakryiko }
174b1a7a480SAndrii Nakryiko }
175b1a7a480SAndrii Nakryiko }
176b1a7a480SAndrii Nakryiko
17757875408SAndrii Nakryiko /* (FIXED) get actual log size */
17857875408SAndrii Nakryiko opts.log_buf = logs.buf;
17957875408SAndrii Nakryiko opts.log_level = log_level | 8; /* BPF_LOG_FIXED */
18057875408SAndrii Nakryiko opts.log_size = sizeof(logs.buf);
181be983f44SAndrii Nakryiko opts.log_true_size = 0;
18257875408SAndrii Nakryiko res = load_prog(&opts, expect_load_error);
18357875408SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "prog_load_res_fixed");
18457875408SAndrii Nakryiko
18557875408SAndrii Nakryiko log_true_sz_fixed = opts.log_true_size;
18657875408SAndrii Nakryiko ASSERT_GT(log_true_sz_fixed, 0, "log_true_sz_fixed");
18757875408SAndrii Nakryiko
188be983f44SAndrii Nakryiko /* (FIXED, NULL) get actual log size */
189be983f44SAndrii Nakryiko opts.log_buf = NULL;
190be983f44SAndrii Nakryiko opts.log_level = log_level | 8; /* BPF_LOG_FIXED */
191be983f44SAndrii Nakryiko opts.log_size = 0;
192be983f44SAndrii Nakryiko opts.log_true_size = 0;
193be983f44SAndrii Nakryiko res = load_prog(&opts, expect_load_error);
194be983f44SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "prog_load_res_fixed_null");
195be983f44SAndrii Nakryiko ASSERT_EQ(opts.log_true_size, log_true_sz_fixed, "log_sz_fixed_null_eq");
196be983f44SAndrii Nakryiko
19757875408SAndrii Nakryiko /* (ROLLING) get actual log size */
19857875408SAndrii Nakryiko opts.log_buf = logs.buf;
19957875408SAndrii Nakryiko opts.log_level = log_level;
20057875408SAndrii Nakryiko opts.log_size = sizeof(logs.buf);
201be983f44SAndrii Nakryiko opts.log_true_size = 0;
20257875408SAndrii Nakryiko res = load_prog(&opts, expect_load_error);
20357875408SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "prog_load_res_rolling");
20457875408SAndrii Nakryiko
20557875408SAndrii Nakryiko log_true_sz_rolling = opts.log_true_size;
20657875408SAndrii Nakryiko ASSERT_EQ(log_true_sz_rolling, log_true_sz_fixed, "log_true_sz_eq");
20757875408SAndrii Nakryiko
208be983f44SAndrii Nakryiko /* (ROLLING, NULL) get actual log size */
209be983f44SAndrii Nakryiko opts.log_buf = NULL;
210be983f44SAndrii Nakryiko opts.log_level = log_level;
211be983f44SAndrii Nakryiko opts.log_size = 0;
212be983f44SAndrii Nakryiko opts.log_true_size = 0;
213be983f44SAndrii Nakryiko res = load_prog(&opts, expect_load_error);
214be983f44SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "prog_load_res_rolling_null");
215be983f44SAndrii Nakryiko ASSERT_EQ(opts.log_true_size, log_true_sz_rolling, "log_true_sz_null_eq");
216be983f44SAndrii Nakryiko
21757875408SAndrii Nakryiko /* (FIXED) expect -ENOSPC for one byte short log */
21857875408SAndrii Nakryiko opts.log_buf = logs.buf;
21957875408SAndrii Nakryiko opts.log_level = log_level | 8; /* BPF_LOG_FIXED */
22057875408SAndrii Nakryiko opts.log_size = log_true_sz_fixed - 1;
221be983f44SAndrii Nakryiko opts.log_true_size = 0;
22257875408SAndrii Nakryiko res = load_prog(&opts, true /* should fail */);
22357875408SAndrii Nakryiko ASSERT_EQ(res, -ENOSPC, "prog_load_res_too_short_fixed");
22457875408SAndrii Nakryiko
22557875408SAndrii Nakryiko /* (FIXED) expect *not* -ENOSPC with exact log_true_size buffer */
22657875408SAndrii Nakryiko opts.log_buf = logs.buf;
22757875408SAndrii Nakryiko opts.log_level = log_level | 8; /* BPF_LOG_FIXED */
22857875408SAndrii Nakryiko opts.log_size = log_true_sz_fixed;
229be983f44SAndrii Nakryiko opts.log_true_size = 0;
23057875408SAndrii Nakryiko res = load_prog(&opts, expect_load_error);
23157875408SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "prog_load_res_just_right_fixed");
23257875408SAndrii Nakryiko
23357875408SAndrii Nakryiko /* (ROLLING) expect -ENOSPC for one byte short log */
23457875408SAndrii Nakryiko opts.log_buf = logs.buf;
23557875408SAndrii Nakryiko opts.log_level = log_level;
23657875408SAndrii Nakryiko opts.log_size = log_true_sz_rolling - 1;
23757875408SAndrii Nakryiko res = load_prog(&opts, true /* should fail */);
23857875408SAndrii Nakryiko ASSERT_EQ(res, -ENOSPC, "prog_load_res_too_short_rolling");
23957875408SAndrii Nakryiko
24057875408SAndrii Nakryiko /* (ROLLING) expect *not* -ENOSPC with exact log_true_size buffer */
24157875408SAndrii Nakryiko opts.log_buf = logs.buf;
24257875408SAndrii Nakryiko opts.log_level = log_level;
24357875408SAndrii Nakryiko opts.log_size = log_true_sz_rolling;
244be983f44SAndrii Nakryiko opts.log_true_size = 0;
24557875408SAndrii Nakryiko res = load_prog(&opts, expect_load_error);
24657875408SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "prog_load_res_just_right_rolling");
24757875408SAndrii Nakryiko
248b1a7a480SAndrii Nakryiko cleanup:
249b1a7a480SAndrii Nakryiko test_log_buf__destroy(skel);
250b1a7a480SAndrii Nakryiko }
251b1a7a480SAndrii Nakryiko
252054b6c78SAndrii Nakryiko static const void *btf_data;
253054b6c78SAndrii Nakryiko static u32 btf_data_sz;
254054b6c78SAndrii Nakryiko
load_btf(struct bpf_btf_load_opts * opts,bool expect_err)255054b6c78SAndrii Nakryiko static int load_btf(struct bpf_btf_load_opts *opts, bool expect_err)
256054b6c78SAndrii Nakryiko {
257054b6c78SAndrii Nakryiko int fd;
258054b6c78SAndrii Nakryiko
259054b6c78SAndrii Nakryiko fd = bpf_btf_load(btf_data, btf_data_sz, opts);
260054b6c78SAndrii Nakryiko if (fd >= 0)
261054b6c78SAndrii Nakryiko close(fd);
262054b6c78SAndrii Nakryiko if (expect_err)
263054b6c78SAndrii Nakryiko ASSERT_LT(fd, 0, "btf_load_failure");
264054b6c78SAndrii Nakryiko else /* !expect_err */
265054b6c78SAndrii Nakryiko ASSERT_GT(fd, 0, "btf_load_success");
266054b6c78SAndrii Nakryiko return fd;
267054b6c78SAndrii Nakryiko }
268054b6c78SAndrii Nakryiko
verif_btf_log_subtest(bool bad_btf)269054b6c78SAndrii Nakryiko static void verif_btf_log_subtest(bool bad_btf)
270054b6c78SAndrii Nakryiko {
271054b6c78SAndrii Nakryiko LIBBPF_OPTS(bpf_btf_load_opts, opts);
272054b6c78SAndrii Nakryiko struct btf *btf;
273054b6c78SAndrii Nakryiko struct btf_type *t;
274054b6c78SAndrii Nakryiko char *exp_log, op_name[32];
275054b6c78SAndrii Nakryiko size_t fixed_log_sz;
276054b6c78SAndrii Nakryiko __u32 log_true_sz_fixed, log_true_sz_rolling;
277054b6c78SAndrii Nakryiko int i, res;
278054b6c78SAndrii Nakryiko
279054b6c78SAndrii Nakryiko /* prepare simple BTF contents */
280054b6c78SAndrii Nakryiko btf = btf__new_empty();
281054b6c78SAndrii Nakryiko if (!ASSERT_OK_PTR(btf, "btf_new_empty"))
282054b6c78SAndrii Nakryiko return;
283054b6c78SAndrii Nakryiko res = btf__add_int(btf, "whatever", 4, 0);
284054b6c78SAndrii Nakryiko if (!ASSERT_GT(res, 0, "btf_add_int_id"))
285054b6c78SAndrii Nakryiko goto cleanup;
286054b6c78SAndrii Nakryiko if (bad_btf) {
287054b6c78SAndrii Nakryiko /* btf__add_int() doesn't allow bad value of size, so we'll just
288054b6c78SAndrii Nakryiko * force-cast btf_type pointer and manually override size to invalid
289054b6c78SAndrii Nakryiko * 3 if we need to simulate failure
290054b6c78SAndrii Nakryiko */
291054b6c78SAndrii Nakryiko t = (void *)btf__type_by_id(btf, res);
292054b6c78SAndrii Nakryiko if (!ASSERT_OK_PTR(t, "int_btf_type"))
293054b6c78SAndrii Nakryiko goto cleanup;
294054b6c78SAndrii Nakryiko t->size = 3;
295054b6c78SAndrii Nakryiko }
296054b6c78SAndrii Nakryiko
297054b6c78SAndrii Nakryiko btf_data = btf__raw_data(btf, &btf_data_sz);
298054b6c78SAndrii Nakryiko if (!ASSERT_OK_PTR(btf_data, "btf_data"))
299054b6c78SAndrii Nakryiko goto cleanup;
300054b6c78SAndrii Nakryiko
301054b6c78SAndrii Nakryiko load_btf(&opts, bad_btf);
302054b6c78SAndrii Nakryiko
303054b6c78SAndrii Nakryiko opts.log_buf = logs.reference;
304054b6c78SAndrii Nakryiko opts.log_size = sizeof(logs.reference);
305054b6c78SAndrii Nakryiko opts.log_level = 1 | 8 /* BPF_LOG_FIXED */;
306054b6c78SAndrii Nakryiko load_btf(&opts, bad_btf);
307054b6c78SAndrii Nakryiko
308054b6c78SAndrii Nakryiko fixed_log_sz = strlen(logs.reference) + 1;
309054b6c78SAndrii Nakryiko if (!ASSERT_GT(fixed_log_sz, 50, "fixed_log_sz"))
310054b6c78SAndrii Nakryiko goto cleanup;
311054b6c78SAndrii Nakryiko memset(logs.reference + fixed_log_sz, 0, sizeof(logs.reference) - fixed_log_sz);
312054b6c78SAndrii Nakryiko
313054b6c78SAndrii Nakryiko /* validate BPF_LOG_FIXED truncation works as verifier log used to work */
314054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
315054b6c78SAndrii Nakryiko opts.log_level = 1 | 8; /* fixed-length log */
316054b6c78SAndrii Nakryiko opts.log_size = 25;
317054b6c78SAndrii Nakryiko res = load_btf(&opts, true);
318054b6c78SAndrii Nakryiko ASSERT_EQ(res, -ENOSPC, "half_log_fd");
319054b6c78SAndrii Nakryiko ASSERT_EQ(strlen(logs.buf), 24, "log_fixed_25");
320054b6c78SAndrii Nakryiko ASSERT_STRNEQ(logs.buf, logs.reference, 24, op_name);
321054b6c78SAndrii Nakryiko
322054b6c78SAndrii Nakryiko /* validate rolling verifier log logic: try all variations of log buf
323054b6c78SAndrii Nakryiko * length to force various truncation scenarios
324054b6c78SAndrii Nakryiko */
325054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
326054b6c78SAndrii Nakryiko opts.log_level = 1; /* rolling log */
327054b6c78SAndrii Nakryiko
328054b6c78SAndrii Nakryiko /* prefill logs.buf with 'A's to detect any write beyond allowed length */
329054b6c78SAndrii Nakryiko memset(logs.filler, 'A', sizeof(logs.filler));
330054b6c78SAndrii Nakryiko logs.filler[sizeof(logs.filler) - 1] = '\0';
331054b6c78SAndrii Nakryiko memset(logs.buf, 'A', sizeof(logs.buf));
332054b6c78SAndrii Nakryiko logs.buf[sizeof(logs.buf) - 1] = '\0';
333054b6c78SAndrii Nakryiko
334054b6c78SAndrii Nakryiko for (i = 1; i < fixed_log_sz; i++) {
335054b6c78SAndrii Nakryiko opts.log_size = i;
336054b6c78SAndrii Nakryiko
337054b6c78SAndrii Nakryiko snprintf(op_name, sizeof(op_name), "log_roll_btf_load_%d", i);
338054b6c78SAndrii Nakryiko res = load_btf(&opts, true);
339054b6c78SAndrii Nakryiko if (!ASSERT_EQ(res, -ENOSPC, op_name))
340054b6c78SAndrii Nakryiko goto cleanup;
341054b6c78SAndrii Nakryiko
342054b6c78SAndrii Nakryiko exp_log = logs.reference + fixed_log_sz - i;
343054b6c78SAndrii Nakryiko snprintf(op_name, sizeof(op_name), "log_roll_contents_%d", i);
344054b6c78SAndrii Nakryiko if (!ASSERT_STREQ(logs.buf, exp_log, op_name)) {
345054b6c78SAndrii Nakryiko printf("CMP:%d\nS1:'%s'\nS2:'%s'\n",
346054b6c78SAndrii Nakryiko strcmp(logs.buf, exp_log),
347054b6c78SAndrii Nakryiko logs.buf, exp_log);
348054b6c78SAndrii Nakryiko goto cleanup;
349054b6c78SAndrii Nakryiko }
350054b6c78SAndrii Nakryiko
351054b6c78SAndrii Nakryiko /* check that unused portions of logs.buf are not overwritten */
352054b6c78SAndrii Nakryiko snprintf(op_name, sizeof(op_name), "log_roll_unused_tail_%d", i);
353054b6c78SAndrii Nakryiko if (!ASSERT_STREQ(logs.buf + i, logs.filler + i, op_name)) {
354054b6c78SAndrii Nakryiko printf("CMP:%d\nS1:'%s'\nS2:'%s'\n",
355054b6c78SAndrii Nakryiko strcmp(logs.buf + i, logs.filler + i),
356054b6c78SAndrii Nakryiko logs.buf + i, logs.filler + i);
357054b6c78SAndrii Nakryiko goto cleanup;
358054b6c78SAndrii Nakryiko }
359054b6c78SAndrii Nakryiko }
360054b6c78SAndrii Nakryiko
361054b6c78SAndrii Nakryiko /* (FIXED) get actual log size */
362054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
363054b6c78SAndrii Nakryiko opts.log_level = 1 | 8; /* BPF_LOG_FIXED */
364054b6c78SAndrii Nakryiko opts.log_size = sizeof(logs.buf);
365054b6c78SAndrii Nakryiko opts.log_true_size = 0;
366054b6c78SAndrii Nakryiko res = load_btf(&opts, bad_btf);
367054b6c78SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "btf_load_res_fixed");
368054b6c78SAndrii Nakryiko
369054b6c78SAndrii Nakryiko log_true_sz_fixed = opts.log_true_size;
370054b6c78SAndrii Nakryiko ASSERT_GT(log_true_sz_fixed, 0, "log_true_sz_fixed");
371054b6c78SAndrii Nakryiko
372054b6c78SAndrii Nakryiko /* (FIXED, NULL) get actual log size */
373054b6c78SAndrii Nakryiko opts.log_buf = NULL;
374054b6c78SAndrii Nakryiko opts.log_level = 1 | 8; /* BPF_LOG_FIXED */
375054b6c78SAndrii Nakryiko opts.log_size = 0;
376054b6c78SAndrii Nakryiko opts.log_true_size = 0;
377054b6c78SAndrii Nakryiko res = load_btf(&opts, bad_btf);
378054b6c78SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "btf_load_res_fixed_null");
379054b6c78SAndrii Nakryiko ASSERT_EQ(opts.log_true_size, log_true_sz_fixed, "log_sz_fixed_null_eq");
380054b6c78SAndrii Nakryiko
381054b6c78SAndrii Nakryiko /* (ROLLING) get actual log size */
382054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
383054b6c78SAndrii Nakryiko opts.log_level = 1;
384054b6c78SAndrii Nakryiko opts.log_size = sizeof(logs.buf);
385054b6c78SAndrii Nakryiko opts.log_true_size = 0;
386054b6c78SAndrii Nakryiko res = load_btf(&opts, bad_btf);
387054b6c78SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "btf_load_res_rolling");
388054b6c78SAndrii Nakryiko
389054b6c78SAndrii Nakryiko log_true_sz_rolling = opts.log_true_size;
390054b6c78SAndrii Nakryiko ASSERT_EQ(log_true_sz_rolling, log_true_sz_fixed, "log_true_sz_eq");
391054b6c78SAndrii Nakryiko
392054b6c78SAndrii Nakryiko /* (ROLLING, NULL) get actual log size */
393054b6c78SAndrii Nakryiko opts.log_buf = NULL;
394054b6c78SAndrii Nakryiko opts.log_level = 1;
395054b6c78SAndrii Nakryiko opts.log_size = 0;
396054b6c78SAndrii Nakryiko opts.log_true_size = 0;
397054b6c78SAndrii Nakryiko res = load_btf(&opts, bad_btf);
398054b6c78SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "btf_load_res_rolling_null");
399054b6c78SAndrii Nakryiko ASSERT_EQ(opts.log_true_size, log_true_sz_rolling, "log_true_sz_null_eq");
400054b6c78SAndrii Nakryiko
401054b6c78SAndrii Nakryiko /* (FIXED) expect -ENOSPC for one byte short log */
402054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
403054b6c78SAndrii Nakryiko opts.log_level = 1 | 8; /* BPF_LOG_FIXED */
404054b6c78SAndrii Nakryiko opts.log_size = log_true_sz_fixed - 1;
405054b6c78SAndrii Nakryiko opts.log_true_size = 0;
406054b6c78SAndrii Nakryiko res = load_btf(&opts, true);
407054b6c78SAndrii Nakryiko ASSERT_EQ(res, -ENOSPC, "btf_load_res_too_short_fixed");
408054b6c78SAndrii Nakryiko
409054b6c78SAndrii Nakryiko /* (FIXED) expect *not* -ENOSPC with exact log_true_size buffer */
410054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
411054b6c78SAndrii Nakryiko opts.log_level = 1 | 8; /* BPF_LOG_FIXED */
412054b6c78SAndrii Nakryiko opts.log_size = log_true_sz_fixed;
413054b6c78SAndrii Nakryiko opts.log_true_size = 0;
414054b6c78SAndrii Nakryiko res = load_btf(&opts, bad_btf);
415054b6c78SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "btf_load_res_just_right_fixed");
416054b6c78SAndrii Nakryiko
417054b6c78SAndrii Nakryiko /* (ROLLING) expect -ENOSPC for one byte short log */
418054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
419054b6c78SAndrii Nakryiko opts.log_level = 1;
420054b6c78SAndrii Nakryiko opts.log_size = log_true_sz_rolling - 1;
421054b6c78SAndrii Nakryiko res = load_btf(&opts, true);
422054b6c78SAndrii Nakryiko ASSERT_EQ(res, -ENOSPC, "btf_load_res_too_short_rolling");
423054b6c78SAndrii Nakryiko
424054b6c78SAndrii Nakryiko /* (ROLLING) expect *not* -ENOSPC with exact log_true_size buffer */
425054b6c78SAndrii Nakryiko opts.log_buf = logs.buf;
426054b6c78SAndrii Nakryiko opts.log_level = 1;
427054b6c78SAndrii Nakryiko opts.log_size = log_true_sz_rolling;
428054b6c78SAndrii Nakryiko opts.log_true_size = 0;
429054b6c78SAndrii Nakryiko res = load_btf(&opts, bad_btf);
430054b6c78SAndrii Nakryiko ASSERT_NEQ(res, -ENOSPC, "btf_load_res_just_right_rolling");
431054b6c78SAndrii Nakryiko
432054b6c78SAndrii Nakryiko cleanup:
433054b6c78SAndrii Nakryiko btf__free(btf);
434054b6c78SAndrii Nakryiko }
435054b6c78SAndrii Nakryiko
test_verifier_log(void)436b1a7a480SAndrii Nakryiko void test_verifier_log(void)
437b1a7a480SAndrii Nakryiko {
438b1a7a480SAndrii Nakryiko if (test__start_subtest("good_prog-level1"))
439b1a7a480SAndrii Nakryiko verif_log_subtest("good_prog", false, 1);
440b1a7a480SAndrii Nakryiko if (test__start_subtest("good_prog-level2"))
441b1a7a480SAndrii Nakryiko verif_log_subtest("good_prog", false, 2);
442b1a7a480SAndrii Nakryiko if (test__start_subtest("bad_prog-level1"))
443b1a7a480SAndrii Nakryiko verif_log_subtest("bad_prog", true, 1);
444b1a7a480SAndrii Nakryiko if (test__start_subtest("bad_prog-level2"))
445b1a7a480SAndrii Nakryiko verif_log_subtest("bad_prog", true, 2);
446054b6c78SAndrii Nakryiko if (test__start_subtest("bad_btf"))
447054b6c78SAndrii Nakryiko verif_btf_log_subtest(true /* bad btf */);
448054b6c78SAndrii Nakryiko if (test__start_subtest("good_btf"))
449054b6c78SAndrii Nakryiko verif_btf_log_subtest(false /* !bad btf */);
450b1a7a480SAndrii Nakryiko }
451