Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3#include <linux/capability.h>
4#include <stdlib.h>
5#include <regex.h>
6#include <test_progs.h>
7#include <bpf/btf.h>
8
9#include "autoconf_helper.h"
10#include "unpriv_helpers.h"
11#include "cap_helpers.h"
12
13#define str_has_pfx(str, pfx) \
14 (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
15
16#define TEST_LOADER_LOG_BUF_SZ 2097152
17
18#define TEST_TAG_EXPECT_FAILURE "comment:test_expect_failure"
19#define TEST_TAG_EXPECT_SUCCESS "comment:test_expect_success"
20#define TEST_TAG_EXPECT_MSG_PFX "comment:test_expect_msg="
21#define TEST_TAG_EXPECT_REGEX_PFX "comment:test_expect_regex="
22#define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv"
23#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv"
24#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv="
25#define TEST_TAG_EXPECT_REGEX_PFX_UNPRIV "comment:test_expect_regex_unpriv="
26#define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level="
27#define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags="
28#define TEST_TAG_DESCRIPTION_PFX "comment:test_description="
29#define TEST_TAG_RETVAL_PFX "comment:test_retval="
30#define TEST_TAG_RETVAL_PFX_UNPRIV "comment:test_retval_unpriv="
31#define TEST_TAG_AUXILIARY "comment:test_auxiliary"
32#define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv"
33#define TEST_BTF_PATH "comment:test_btf_path="
34
35/* Warning: duplicated in bpf_misc.h */
36#define POINTER_VALUE 0xcafe4all
37#define TEST_DATA_LEN 64
38
39#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
40#define EFFICIENT_UNALIGNED_ACCESS 1
41#else
42#define EFFICIENT_UNALIGNED_ACCESS 0
43#endif
44
45static int sysctl_unpriv_disabled = -1;
46
47enum mode {
48 PRIV = 1,
49 UNPRIV = 2
50};
51
52struct expect_msg {
53 const char *substr; /* substring match */
54 const char *regex_str; /* regex-based match */
55 regex_t regex;
56};
57
58struct test_subspec {
59 char *name;
60 bool expect_failure;
61 struct expect_msg *expect_msgs;
62 size_t expect_msg_cnt;
63 int retval;
64 bool execute;
65};
66
67struct test_spec {
68 const char *prog_name;
69 struct test_subspec priv;
70 struct test_subspec unpriv;
71 const char *btf_custom_path;
72 int log_level;
73 int prog_flags;
74 int mode_mask;
75 bool auxiliary;
76 bool valid;
77};
78
79static int tester_init(struct test_loader *tester)
80{
81 if (!tester->log_buf) {
82 tester->log_buf_sz = TEST_LOADER_LOG_BUF_SZ;
83 tester->log_buf = calloc(tester->log_buf_sz, 1);
84 if (!ASSERT_OK_PTR(tester->log_buf, "tester_log_buf"))
85 return -ENOMEM;
86 }
87
88 return 0;
89}
90
91void test_loader_fini(struct test_loader *tester)
92{
93 if (!tester)
94 return;
95
96 free(tester->log_buf);
97}
98
99static void free_test_spec(struct test_spec *spec)
100{
101 int i;
102
103 /* Deallocate expect_msgs arrays. */
104 for (i = 0; i < spec->priv.expect_msg_cnt; i++)
105 if (spec->priv.expect_msgs[i].regex_str)
106 regfree(&spec->priv.expect_msgs[i].regex);
107 for (i = 0; i < spec->unpriv.expect_msg_cnt; i++)
108 if (spec->unpriv.expect_msgs[i].regex_str)
109 regfree(&spec->unpriv.expect_msgs[i].regex);
110
111 free(spec->priv.name);
112 free(spec->unpriv.name);
113 free(spec->priv.expect_msgs);
114 free(spec->unpriv.expect_msgs);
115
116 spec->priv.name = NULL;
117 spec->unpriv.name = NULL;
118 spec->priv.expect_msgs = NULL;
119 spec->unpriv.expect_msgs = NULL;
120}
121
122static int push_msg(const char *substr, const char *regex_str, struct test_subspec *subspec)
123{
124 void *tmp;
125 int regcomp_res;
126 char error_msg[100];
127 struct expect_msg *msg;
128
129 tmp = realloc(subspec->expect_msgs,
130 (1 + subspec->expect_msg_cnt) * sizeof(struct expect_msg));
131 if (!tmp) {
132 ASSERT_FAIL("failed to realloc memory for messages\n");
133 return -ENOMEM;
134 }
135 subspec->expect_msgs = tmp;
136 msg = &subspec->expect_msgs[subspec->expect_msg_cnt];
137
138 if (substr) {
139 msg->substr = substr;
140 msg->regex_str = NULL;
141 } else {
142 msg->regex_str = regex_str;
143 msg->substr = NULL;
144 regcomp_res = regcomp(&msg->regex, regex_str, REG_EXTENDED|REG_NEWLINE);
145 if (regcomp_res != 0) {
146 regerror(regcomp_res, &msg->regex, error_msg, sizeof(error_msg));
147 PRINT_FAIL("Regexp compilation error in '%s': '%s'\n",
148 regex_str, error_msg);
149 return -EINVAL;
150 }
151 }
152
153 subspec->expect_msg_cnt += 1;
154 return 0;
155}
156
157static int parse_int(const char *str, int *val, const char *name)
158{
159 char *end;
160 long tmp;
161
162 errno = 0;
163 if (str_has_pfx(str, "0x"))
164 tmp = strtol(str + 2, &end, 16);
165 else
166 tmp = strtol(str, &end, 10);
167 if (errno || end[0] != '\0') {
168 PRINT_FAIL("failed to parse %s from '%s'\n", name, str);
169 return -EINVAL;
170 }
171 *val = tmp;
172 return 0;
173}
174
175static int parse_retval(const char *str, int *val, const char *name)
176{
177 struct {
178 char *name;
179 int val;
180 } named_values[] = {
181 { "INT_MIN" , INT_MIN },
182 { "POINTER_VALUE", POINTER_VALUE },
183 { "TEST_DATA_LEN", TEST_DATA_LEN },
184 };
185 int i;
186
187 for (i = 0; i < ARRAY_SIZE(named_values); ++i) {
188 if (strcmp(str, named_values[i].name) != 0)
189 continue;
190 *val = named_values[i].val;
191 return 0;
192 }
193
194 return parse_int(str, val, name);
195}
196
197static void update_flags(int *flags, int flag, bool clear)
198{
199 if (clear)
200 *flags &= ~flag;
201 else
202 *flags |= flag;
203}
204
205/* Uses btf_decl_tag attributes to describe the expected test
206 * behavior, see bpf_misc.h for detailed description of each attribute
207 * and attribute combinations.
208 */
209static int parse_test_spec(struct test_loader *tester,
210 struct bpf_object *obj,
211 struct bpf_program *prog,
212 struct test_spec *spec)
213{
214 const char *description = NULL;
215 bool has_unpriv_result = false;
216 bool has_unpriv_retval = false;
217 int func_id, i, err = 0;
218 struct btf *btf;
219
220 memset(spec, 0, sizeof(*spec));
221
222 spec->prog_name = bpf_program__name(prog);
223 spec->prog_flags = testing_prog_flags();
224
225 btf = bpf_object__btf(obj);
226 if (!btf) {
227 ASSERT_FAIL("BPF object has no BTF");
228 return -EINVAL;
229 }
230
231 func_id = btf__find_by_name_kind(btf, spec->prog_name, BTF_KIND_FUNC);
232 if (func_id < 0) {
233 ASSERT_FAIL("failed to find FUNC BTF type for '%s'", spec->prog_name);
234 return -EINVAL;
235 }
236
237 for (i = 1; i < btf__type_cnt(btf); i++) {
238 const char *s, *val, *msg;
239 const struct btf_type *t;
240 bool clear;
241 int flags;
242
243 t = btf__type_by_id(btf, i);
244 if (!btf_is_decl_tag(t))
245 continue;
246
247 if (t->type != func_id || btf_decl_tag(t)->component_idx != -1)
248 continue;
249
250 s = btf__str_by_offset(btf, t->name_off);
251 if (str_has_pfx(s, TEST_TAG_DESCRIPTION_PFX)) {
252 description = s + sizeof(TEST_TAG_DESCRIPTION_PFX) - 1;
253 } else if (strcmp(s, TEST_TAG_EXPECT_FAILURE) == 0) {
254 spec->priv.expect_failure = true;
255 spec->mode_mask |= PRIV;
256 } else if (strcmp(s, TEST_TAG_EXPECT_SUCCESS) == 0) {
257 spec->priv.expect_failure = false;
258 spec->mode_mask |= PRIV;
259 } else if (strcmp(s, TEST_TAG_EXPECT_FAILURE_UNPRIV) == 0) {
260 spec->unpriv.expect_failure = true;
261 spec->mode_mask |= UNPRIV;
262 has_unpriv_result = true;
263 } else if (strcmp(s, TEST_TAG_EXPECT_SUCCESS_UNPRIV) == 0) {
264 spec->unpriv.expect_failure = false;
265 spec->mode_mask |= UNPRIV;
266 has_unpriv_result = true;
267 } else if (strcmp(s, TEST_TAG_AUXILIARY) == 0) {
268 spec->auxiliary = true;
269 spec->mode_mask |= PRIV;
270 } else if (strcmp(s, TEST_TAG_AUXILIARY_UNPRIV) == 0) {
271 spec->auxiliary = true;
272 spec->mode_mask |= UNPRIV;
273 } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX)) {
274 msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX) - 1;
275 err = push_msg(msg, NULL, &spec->priv);
276 if (err)
277 goto cleanup;
278 spec->mode_mask |= PRIV;
279 } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV)) {
280 msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX_UNPRIV) - 1;
281 err = push_msg(msg, NULL, &spec->unpriv);
282 if (err)
283 goto cleanup;
284 spec->mode_mask |= UNPRIV;
285 } else if (str_has_pfx(s, TEST_TAG_EXPECT_REGEX_PFX)) {
286 msg = s + sizeof(TEST_TAG_EXPECT_REGEX_PFX) - 1;
287 err = push_msg(NULL, msg, &spec->priv);
288 if (err)
289 goto cleanup;
290 spec->mode_mask |= PRIV;
291 } else if (str_has_pfx(s, TEST_TAG_EXPECT_REGEX_PFX_UNPRIV)) {
292 msg = s + sizeof(TEST_TAG_EXPECT_REGEX_PFX_UNPRIV) - 1;
293 err = push_msg(NULL, msg, &spec->unpriv);
294 if (err)
295 goto cleanup;
296 spec->mode_mask |= UNPRIV;
297 } else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX)) {
298 val = s + sizeof(TEST_TAG_RETVAL_PFX) - 1;
299 err = parse_retval(val, &spec->priv.retval, "__retval");
300 if (err)
301 goto cleanup;
302 spec->priv.execute = true;
303 spec->mode_mask |= PRIV;
304 } else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX_UNPRIV)) {
305 val = s + sizeof(TEST_TAG_RETVAL_PFX_UNPRIV) - 1;
306 err = parse_retval(val, &spec->unpriv.retval, "__retval_unpriv");
307 if (err)
308 goto cleanup;
309 spec->mode_mask |= UNPRIV;
310 spec->unpriv.execute = true;
311 has_unpriv_retval = true;
312 } else if (str_has_pfx(s, TEST_TAG_LOG_LEVEL_PFX)) {
313 val = s + sizeof(TEST_TAG_LOG_LEVEL_PFX) - 1;
314 err = parse_int(val, &spec->log_level, "test log level");
315 if (err)
316 goto cleanup;
317 } else if (str_has_pfx(s, TEST_TAG_PROG_FLAGS_PFX)) {
318 val = s + sizeof(TEST_TAG_PROG_FLAGS_PFX) - 1;
319
320 clear = val[0] == '!';
321 if (clear)
322 val++;
323
324 if (strcmp(val, "BPF_F_STRICT_ALIGNMENT") == 0) {
325 update_flags(&spec->prog_flags, BPF_F_STRICT_ALIGNMENT, clear);
326 } else if (strcmp(val, "BPF_F_ANY_ALIGNMENT") == 0) {
327 update_flags(&spec->prog_flags, BPF_F_ANY_ALIGNMENT, clear);
328 } else if (strcmp(val, "BPF_F_TEST_RND_HI32") == 0) {
329 update_flags(&spec->prog_flags, BPF_F_TEST_RND_HI32, clear);
330 } else if (strcmp(val, "BPF_F_TEST_STATE_FREQ") == 0) {
331 update_flags(&spec->prog_flags, BPF_F_TEST_STATE_FREQ, clear);
332 } else if (strcmp(val, "BPF_F_SLEEPABLE") == 0) {
333 update_flags(&spec->prog_flags, BPF_F_SLEEPABLE, clear);
334 } else if (strcmp(val, "BPF_F_XDP_HAS_FRAGS") == 0) {
335 update_flags(&spec->prog_flags, BPF_F_XDP_HAS_FRAGS, clear);
336 } else if (strcmp(val, "BPF_F_TEST_REG_INVARIANTS") == 0) {
337 update_flags(&spec->prog_flags, BPF_F_TEST_REG_INVARIANTS, clear);
338 } else /* assume numeric value */ {
339 err = parse_int(val, &flags, "test prog flags");
340 if (err)
341 goto cleanup;
342 update_flags(&spec->prog_flags, flags, clear);
343 }
344 } else if (str_has_pfx(s, TEST_BTF_PATH)) {
345 spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1;
346 }
347 }
348
349 if (spec->mode_mask == 0)
350 spec->mode_mask = PRIV;
351
352 if (!description)
353 description = spec->prog_name;
354
355 if (spec->mode_mask & PRIV) {
356 spec->priv.name = strdup(description);
357 if (!spec->priv.name) {
358 PRINT_FAIL("failed to allocate memory for priv.name\n");
359 err = -ENOMEM;
360 goto cleanup;
361 }
362 }
363
364 if (spec->mode_mask & UNPRIV) {
365 int descr_len = strlen(description);
366 const char *suffix = " @unpriv";
367 char *name;
368
369 name = malloc(descr_len + strlen(suffix) + 1);
370 if (!name) {
371 PRINT_FAIL("failed to allocate memory for unpriv.name\n");
372 err = -ENOMEM;
373 goto cleanup;
374 }
375
376 strcpy(name, description);
377 strcpy(&name[descr_len], suffix);
378 spec->unpriv.name = name;
379 }
380
381 if (spec->mode_mask & (PRIV | UNPRIV)) {
382 if (!has_unpriv_result)
383 spec->unpriv.expect_failure = spec->priv.expect_failure;
384
385 if (!has_unpriv_retval) {
386 spec->unpriv.retval = spec->priv.retval;
387 spec->unpriv.execute = spec->priv.execute;
388 }
389
390 if (!spec->unpriv.expect_msgs) {
391 for (i = 0; i < spec->priv.expect_msg_cnt; i++) {
392 struct expect_msg *msg = &spec->priv.expect_msgs[i];
393
394 err = push_msg(msg->substr, msg->regex_str, &spec->unpriv);
395 if (err)
396 goto cleanup;
397 }
398 }
399 }
400
401 spec->valid = true;
402
403 return 0;
404
405cleanup:
406 free_test_spec(spec);
407 return err;
408}
409
410static void prepare_case(struct test_loader *tester,
411 struct test_spec *spec,
412 struct bpf_object *obj,
413 struct bpf_program *prog)
414{
415 int min_log_level = 0, prog_flags;
416
417 if (env.verbosity > VERBOSE_NONE)
418 min_log_level = 1;
419 if (env.verbosity > VERBOSE_VERY)
420 min_log_level = 2;
421
422 bpf_program__set_log_buf(prog, tester->log_buf, tester->log_buf_sz);
423
424 /* Make sure we set at least minimal log level, unless test requires
425 * even higher level already. Make sure to preserve independent log
426 * level 4 (verifier stats), though.
427 */
428 if ((spec->log_level & 3) < min_log_level)
429 bpf_program__set_log_level(prog, (spec->log_level & 4) | min_log_level);
430 else
431 bpf_program__set_log_level(prog, spec->log_level);
432
433 prog_flags = bpf_program__flags(prog);
434 bpf_program__set_flags(prog, prog_flags | spec->prog_flags);
435
436 tester->log_buf[0] = '\0';
437 tester->next_match_pos = 0;
438}
439
440static void emit_verifier_log(const char *log_buf, bool force)
441{
442 if (!force && env.verbosity == VERBOSE_NONE)
443 return;
444 fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log_buf);
445}
446
447static void validate_case(struct test_loader *tester,
448 struct test_subspec *subspec,
449 struct bpf_object *obj,
450 struct bpf_program *prog,
451 int load_err)
452{
453 int i, j, err;
454 char *match;
455 regmatch_t reg_match[1];
456
457 for (i = 0; i < subspec->expect_msg_cnt; i++) {
458 struct expect_msg *msg = &subspec->expect_msgs[i];
459
460 if (msg->substr) {
461 match = strstr(tester->log_buf + tester->next_match_pos, msg->substr);
462 if (match)
463 tester->next_match_pos = match - tester->log_buf + strlen(msg->substr);
464 } else {
465 err = regexec(&msg->regex,
466 tester->log_buf + tester->next_match_pos, 1, reg_match, 0);
467 if (err == 0) {
468 match = tester->log_buf + tester->next_match_pos + reg_match[0].rm_so;
469 tester->next_match_pos += reg_match[0].rm_eo;
470 } else {
471 match = NULL;
472 }
473 }
474
475 if (!ASSERT_OK_PTR(match, "expect_msg")) {
476 if (env.verbosity == VERBOSE_NONE)
477 emit_verifier_log(tester->log_buf, true /*force*/);
478 for (j = 0; j <= i; j++) {
479 msg = &subspec->expect_msgs[j];
480 fprintf(stderr, "%s %s: '%s'\n",
481 j < i ? "MATCHED " : "EXPECTED",
482 msg->substr ? "SUBSTR" : " REGEX",
483 msg->substr ?: msg->regex_str);
484 }
485 return;
486 }
487 }
488}
489
490struct cap_state {
491 __u64 old_caps;
492 bool initialized;
493};
494
495static int drop_capabilities(struct cap_state *caps)
496{
497 const __u64 caps_to_drop = (1ULL << CAP_SYS_ADMIN | 1ULL << CAP_NET_ADMIN |
498 1ULL << CAP_PERFMON | 1ULL << CAP_BPF);
499 int err;
500
501 err = cap_disable_effective(caps_to_drop, &caps->old_caps);
502 if (err) {
503 PRINT_FAIL("failed to drop capabilities: %i, %s\n", err, strerror(err));
504 return err;
505 }
506
507 caps->initialized = true;
508 return 0;
509}
510
511static int restore_capabilities(struct cap_state *caps)
512{
513 int err;
514
515 if (!caps->initialized)
516 return 0;
517
518 err = cap_enable_effective(caps->old_caps, NULL);
519 if (err)
520 PRINT_FAIL("failed to restore capabilities: %i, %s\n", err, strerror(err));
521 caps->initialized = false;
522 return err;
523}
524
525static bool can_execute_unpriv(struct test_loader *tester, struct test_spec *spec)
526{
527 if (sysctl_unpriv_disabled < 0)
528 sysctl_unpriv_disabled = get_unpriv_disabled() ? 1 : 0;
529 if (sysctl_unpriv_disabled)
530 return false;
531 if ((spec->prog_flags & BPF_F_ANY_ALIGNMENT) && !EFFICIENT_UNALIGNED_ACCESS)
532 return false;
533 return true;
534}
535
536static bool is_unpriv_capable_map(struct bpf_map *map)
537{
538 enum bpf_map_type type;
539 __u32 flags;
540
541 type = bpf_map__type(map);
542
543 switch (type) {
544 case BPF_MAP_TYPE_HASH:
545 case BPF_MAP_TYPE_PERCPU_HASH:
546 case BPF_MAP_TYPE_HASH_OF_MAPS:
547 flags = bpf_map__map_flags(map);
548 return !(flags & BPF_F_ZERO_SEED);
549 case BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE:
550 case BPF_MAP_TYPE_ARRAY:
551 case BPF_MAP_TYPE_RINGBUF:
552 case BPF_MAP_TYPE_PROG_ARRAY:
553 case BPF_MAP_TYPE_CGROUP_ARRAY:
554 case BPF_MAP_TYPE_PERCPU_ARRAY:
555 case BPF_MAP_TYPE_USER_RINGBUF:
556 case BPF_MAP_TYPE_ARRAY_OF_MAPS:
557 case BPF_MAP_TYPE_CGROUP_STORAGE:
558 case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
559 return true;
560 default:
561 return false;
562 }
563}
564
565static int do_prog_test_run(int fd_prog, int *retval, bool empty_opts)
566{
567 __u8 tmp_out[TEST_DATA_LEN << 2] = {};
568 __u8 tmp_in[TEST_DATA_LEN] = {};
569 int err, saved_errno;
570 LIBBPF_OPTS(bpf_test_run_opts, topts,
571 .data_in = tmp_in,
572 .data_size_in = sizeof(tmp_in),
573 .data_out = tmp_out,
574 .data_size_out = sizeof(tmp_out),
575 .repeat = 1,
576 );
577
578 if (empty_opts) {
579 memset(&topts, 0, sizeof(struct bpf_test_run_opts));
580 topts.sz = sizeof(struct bpf_test_run_opts);
581 }
582 err = bpf_prog_test_run_opts(fd_prog, &topts);
583 saved_errno = errno;
584
585 if (err) {
586 PRINT_FAIL("FAIL: Unexpected bpf_prog_test_run error: %d (%s) ",
587 saved_errno, strerror(saved_errno));
588 return err;
589 }
590
591 ASSERT_OK(0, "bpf_prog_test_run");
592 *retval = topts.retval;
593
594 return 0;
595}
596
597static bool should_do_test_run(struct test_spec *spec, struct test_subspec *subspec)
598{
599 if (!subspec->execute)
600 return false;
601
602 if (subspec->expect_failure)
603 return false;
604
605 if ((spec->prog_flags & BPF_F_ANY_ALIGNMENT) && !EFFICIENT_UNALIGNED_ACCESS) {
606 if (env.verbosity != VERBOSE_NONE)
607 printf("alignment prevents execution\n");
608 return false;
609 }
610
611 return true;
612}
613
614/* this function is forced noinline and has short generic name to look better
615 * in test_progs output (in case of a failure)
616 */
617static noinline
618void run_subtest(struct test_loader *tester,
619 struct bpf_object_open_opts *open_opts,
620 const void *obj_bytes,
621 size_t obj_byte_cnt,
622 struct test_spec *specs,
623 struct test_spec *spec,
624 bool unpriv)
625{
626 struct test_subspec *subspec = unpriv ? &spec->unpriv : &spec->priv;
627 struct bpf_program *tprog = NULL, *tprog_iter;
628 struct test_spec *spec_iter;
629 struct cap_state caps = {};
630 struct bpf_object *tobj;
631 struct bpf_map *map;
632 int retval, err, i;
633 bool should_load;
634
635 if (!test__start_subtest(subspec->name))
636 return;
637
638 if (unpriv) {
639 if (!can_execute_unpriv(tester, spec)) {
640 test__skip();
641 test__end_subtest();
642 return;
643 }
644 if (drop_capabilities(&caps)) {
645 test__end_subtest();
646 return;
647 }
648 }
649
650 /* Implicitly reset to NULL if next test case doesn't specify */
651 open_opts->btf_custom_path = spec->btf_custom_path;
652
653 tobj = bpf_object__open_mem(obj_bytes, obj_byte_cnt, open_opts);
654 if (!ASSERT_OK_PTR(tobj, "obj_open_mem")) /* shouldn't happen */
655 goto subtest_cleanup;
656
657 i = 0;
658 bpf_object__for_each_program(tprog_iter, tobj) {
659 spec_iter = &specs[i++];
660 should_load = false;
661
662 if (spec_iter->valid) {
663 if (strcmp(bpf_program__name(tprog_iter), spec->prog_name) == 0) {
664 tprog = tprog_iter;
665 should_load = true;
666 }
667
668 if (spec_iter->auxiliary &&
669 spec_iter->mode_mask & (unpriv ? UNPRIV : PRIV))
670 should_load = true;
671 }
672
673 bpf_program__set_autoload(tprog_iter, should_load);
674 }
675
676 prepare_case(tester, spec, tobj, tprog);
677
678 /* By default bpf_object__load() automatically creates all
679 * maps declared in the skeleton. Some map types are only
680 * allowed in priv mode. Disable autoload for such maps in
681 * unpriv mode.
682 */
683 bpf_object__for_each_map(map, tobj)
684 bpf_map__set_autocreate(map, !unpriv || is_unpriv_capable_map(map));
685
686 err = bpf_object__load(tobj);
687 if (subspec->expect_failure) {
688 if (!ASSERT_ERR(err, "unexpected_load_success")) {
689 emit_verifier_log(tester->log_buf, false /*force*/);
690 goto tobj_cleanup;
691 }
692 } else {
693 if (!ASSERT_OK(err, "unexpected_load_failure")) {
694 emit_verifier_log(tester->log_buf, true /*force*/);
695 goto tobj_cleanup;
696 }
697 }
698
699 emit_verifier_log(tester->log_buf, false /*force*/);
700 validate_case(tester, subspec, tobj, tprog, err);
701
702 if (should_do_test_run(spec, subspec)) {
703 /* For some reason test_verifier executes programs
704 * with all capabilities restored. Do the same here.
705 */
706 if (restore_capabilities(&caps))
707 goto tobj_cleanup;
708
709 if (tester->pre_execution_cb) {
710 err = tester->pre_execution_cb(tobj);
711 if (err) {
712 PRINT_FAIL("pre_execution_cb failed: %d\n", err);
713 goto tobj_cleanup;
714 }
715 }
716
717 do_prog_test_run(bpf_program__fd(tprog), &retval,
718 bpf_program__type(tprog) == BPF_PROG_TYPE_SYSCALL ? true : false);
719 if (retval != subspec->retval && subspec->retval != POINTER_VALUE) {
720 PRINT_FAIL("Unexpected retval: %d != %d\n", retval, subspec->retval);
721 goto tobj_cleanup;
722 }
723 }
724
725tobj_cleanup:
726 bpf_object__close(tobj);
727subtest_cleanup:
728 test__end_subtest();
729 restore_capabilities(&caps);
730}
731
732static void process_subtest(struct test_loader *tester,
733 const char *skel_name,
734 skel_elf_bytes_fn elf_bytes_factory)
735{
736 LIBBPF_OPTS(bpf_object_open_opts, open_opts, .object_name = skel_name);
737 struct test_spec *specs = NULL;
738 struct bpf_object *obj = NULL;
739 struct bpf_program *prog;
740 const void *obj_bytes;
741 int err, i, nr_progs;
742 size_t obj_byte_cnt;
743
744 if (tester_init(tester) < 0)
745 return; /* failed to initialize tester */
746
747 obj_bytes = elf_bytes_factory(&obj_byte_cnt);
748 obj = bpf_object__open_mem(obj_bytes, obj_byte_cnt, &open_opts);
749 if (!ASSERT_OK_PTR(obj, "obj_open_mem"))
750 return;
751
752 nr_progs = 0;
753 bpf_object__for_each_program(prog, obj)
754 ++nr_progs;
755
756 specs = calloc(nr_progs, sizeof(struct test_spec));
757 if (!ASSERT_OK_PTR(specs, "specs_alloc"))
758 return;
759
760 i = 0;
761 bpf_object__for_each_program(prog, obj) {
762 /* ignore tests for which we can't derive test specification */
763 err = parse_test_spec(tester, obj, prog, &specs[i++]);
764 if (err)
765 PRINT_FAIL("Can't parse test spec for program '%s'\n",
766 bpf_program__name(prog));
767 }
768
769 i = 0;
770 bpf_object__for_each_program(prog, obj) {
771 struct test_spec *spec = &specs[i++];
772
773 if (!spec->valid || spec->auxiliary)
774 continue;
775
776 if (spec->mode_mask & PRIV)
777 run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
778 specs, spec, false);
779 if (spec->mode_mask & UNPRIV)
780 run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
781 specs, spec, true);
782
783 }
784
785 for (i = 0; i < nr_progs; ++i)
786 free_test_spec(&specs[i]);
787 free(specs);
788 bpf_object__close(obj);
789}
790
791void test_loader__run_subtests(struct test_loader *tester,
792 const char *skel_name,
793 skel_elf_bytes_fn elf_bytes_factory)
794{
795 /* see comment in run_subtest() for why we do this function nesting */
796 process_subtest(tester, skel_name, elf_bytes_factory);
797}