aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/bpf/prog_tests/kfunc_dynptr_param.c
blob: c210657d4d0aaae13b1a6e38e5995028af432208 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// SPDX-License-Identifier: GPL-2.0

/*
 * Copyright (c) 2022 Facebook
 * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
 *
 * Author: Roberto Sassu <roberto.sassu@huawei.com>
 */

#include <test_progs.h>
#include "test_kfunc_dynptr_param.skel.h"

static size_t log_buf_sz = 1048576; /* 1 MB */
static char obj_log_buf[1048576];

static struct {
	const char *prog_name;
	const char *expected_verifier_err_msg;
	int expected_runtime_err;
} kfunc_dynptr_tests[] = {
	{"dynptr_type_not_supp",
	 "arg#0 pointer type STRUCT bpf_dynptr_kern points to unsupported dynamic pointer type", 0},
	{"not_valid_dynptr",
	 "arg#0 pointer type STRUCT bpf_dynptr_kern must be valid and initialized", 0},
	{"not_ptr_to_stack", "arg#0 pointer type STRUCT bpf_dynptr_kern not to stack", 0},
	{"dynptr_data_null", NULL, -EBADMSG},
};

static bool kfunc_not_supported;

static int libbpf_print_cb(enum libbpf_print_level level, const char *fmt,
			   va_list args)
{
	if (strcmp(fmt, "libbpf: extern (func ksym) '%s': not found in kernel or module BTFs\n"))
		return 0;

	if (strcmp(va_arg(args, char *), "bpf_verify_pkcs7_signature"))
		return 0;

	kfunc_not_supported = true;
	return 0;
}

static void verify_fail(const char *prog_name, const char *expected_err_msg)
{
	struct test_kfunc_dynptr_param *skel;
	LIBBPF_OPTS(bpf_object_open_opts, opts);
	libbpf_print_fn_t old_print_cb;
	struct bpf_program *prog;
	int err;

	opts.kernel_log_buf = obj_log_buf;
	opts.kernel_log_size = log_buf_sz;
	opts.kernel_log_level = 1;

	skel = test_kfunc_dynptr_param__open_opts(&opts);
	if (!ASSERT_OK_PTR(skel, "test_kfunc_dynptr_param__open_opts"))
		goto cleanup;

	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
		goto cleanup;

	bpf_program__set_autoload(prog, true);

	bpf_map__set_max_entries(skel->maps.ringbuf, getpagesize());

	kfunc_not_supported = false;

	old_print_cb = libbpf_set_print(libbpf_print_cb);
	err = test_kfunc_dynptr_param__load(skel);
	libbpf_set_print(old_print_cb);

	if (err < 0 && kfunc_not_supported) {
		fprintf(stderr,
		  "%s:SKIP:bpf_verify_pkcs7_signature() kfunc not supported\n",
		  __func__);
		test__skip();
		goto cleanup;
	}

	if (!ASSERT_ERR(err, "unexpected load success"))
		goto cleanup;

	if (!ASSERT_OK_PTR(strstr(obj_log_buf, expected_err_msg), "expected_err_msg")) {
		fprintf(stderr, "Expected err_msg: %s\n", expected_err_msg);
		fprintf(stderr, "Verifier output: %s\n", obj_log_buf);
	}

cleanup:
	test_kfunc_dynptr_param__destroy(skel);
}

static void verify_success(const char *prog_name, int expected_runtime_err)
{
	struct test_kfunc_dynptr_param *skel;
	libbpf_print_fn_t old_print_cb;
	struct bpf_program *prog;
	struct bpf_link *link;
	__u32 next_id;
	int err;

	skel = test_kfunc_dynptr_param__open();
	if (!ASSERT_OK_PTR(skel, "test_kfunc_dynptr_param__open"))
		return;

	skel->bss->pid = getpid();

	bpf_map__set_max_entries(skel->maps.ringbuf, getpagesize());

	kfunc_not_supported = false;

	old_print_cb = libbpf_set_print(libbpf_print_cb);
	err = test_kfunc_dynptr_param__load(skel);
	libbpf_set_print(old_print_cb);

	if (err < 0 && kfunc_not_supported) {
		fprintf(stderr,
		  "%s:SKIP:bpf_verify_pkcs7_signature() kfunc not supported\n",
		  __func__);
		test__skip();
		goto cleanup;
	}

	if (!ASSERT_OK(err, "test_kfunc_dynptr_param__load"))
		goto cleanup;

	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
		goto cleanup;

	link = bpf_program__attach(prog);
	if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
		goto cleanup;

	err = bpf_prog_get_next_id(0, &next_id);

	bpf_link__destroy(link);

	if (!ASSERT_OK(err, "bpf_prog_get_next_id"))
		goto cleanup;

	ASSERT_EQ(skel->bss->err, expected_runtime_err, "err");

cleanup:
	test_kfunc_dynptr_param__destroy(skel);
}

void test_kfunc_dynptr_param(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(kfunc_dynptr_tests); i++) {
		if (!test__start_subtest(kfunc_dynptr_tests[i].prog_name))
			continue;

		if (kfunc_dynptr_tests[i].expected_verifier_err_msg)
			verify_fail(kfunc_dynptr_tests[i].prog_name,
			  kfunc_dynptr_tests[i].expected_verifier_err_msg);
		else
			verify_success(kfunc_dynptr_tests[i].prog_name,
				kfunc_dynptr_tests[i].expected_runtime_err);
	}
}