xref: /linux/tools/testing/selftests/bpf/prog_tests/dynptr.c (revision 5fc5768c7ca92895ccd1de94dc521e5a55ae7896)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Facebook */
3 
4 #include <test_progs.h>
5 #include <network_helpers.h>
6 #include "dynptr_fail.skel.h"
7 #include "dynptr_success.skel.h"
8 
9 enum test_setup_type {
10 	SETUP_SYSCALL_SLEEP,
11 	SETUP_SKB_PROG,
12 	SETUP_SKB_PROG_NONLINEAR,
13 	SETUP_SKB_PROG_TP,
14 	SETUP_XDP_PROG,
15 };
16 
17 static struct {
18 	const char *prog_name;
19 	enum test_setup_type type;
20 } success_tests[] = {
21 	{"test_read_write", SETUP_SYSCALL_SLEEP},
22 	{"test_dynptr_data", SETUP_SYSCALL_SLEEP},
23 	{"test_dynptr_copy", SETUP_SYSCALL_SLEEP},
24 	{"test_dynptr_copy_xdp", SETUP_XDP_PROG},
25 	{"test_dynptr_memset_zero", SETUP_SYSCALL_SLEEP},
26 	{"test_dynptr_memset_notzero", SETUP_SYSCALL_SLEEP},
27 	{"test_dynptr_memset_zero_offset", SETUP_SYSCALL_SLEEP},
28 	{"test_dynptr_memset_zero_adjusted", SETUP_SYSCALL_SLEEP},
29 	{"test_dynptr_memset_overflow", SETUP_SYSCALL_SLEEP},
30 	{"test_dynptr_memset_overflow_offset", SETUP_SYSCALL_SLEEP},
31 	{"test_dynptr_memset_readonly", SETUP_SKB_PROG},
32 	{"test_dynptr_memset_xdp_chunks", SETUP_XDP_PROG},
33 	{"test_ringbuf", SETUP_SYSCALL_SLEEP},
34 	{"test_skb_readonly", SETUP_SKB_PROG},
35 	{"test_dynptr_skb_data", SETUP_SKB_PROG},
36 	{"test_dynptr_skb_slice_non_linear", SETUP_SKB_PROG_NONLINEAR},
37 	{"test_dynptr_skb_meta_data", SETUP_SKB_PROG},
38 	{"test_dynptr_skb_meta_flags", SETUP_SKB_PROG},
39 	{"test_adjust", SETUP_SYSCALL_SLEEP},
40 	{"test_adjust_err", SETUP_SYSCALL_SLEEP},
41 	{"test_zero_size_dynptr", SETUP_SYSCALL_SLEEP},
42 	{"test_dynptr_is_null", SETUP_SYSCALL_SLEEP},
43 	{"test_dynptr_is_rdonly", SETUP_SKB_PROG},
44 	{"test_dynptr_clone", SETUP_SKB_PROG},
45 	{"test_dynptr_skb_no_buff", SETUP_SKB_PROG},
46 	{"test_dynptr_skb_strcmp", SETUP_SKB_PROG},
47 	{"test_dynptr_skb_tp_btf", SETUP_SKB_PROG_TP},
48 	{"test_probe_read_user_dynptr", SETUP_XDP_PROG},
49 	{"test_probe_read_kernel_dynptr", SETUP_XDP_PROG},
50 	{"test_probe_read_user_str_dynptr", SETUP_XDP_PROG},
51 	{"test_probe_read_kernel_str_dynptr", SETUP_XDP_PROG},
52 	{"test_copy_from_user_dynptr", SETUP_SYSCALL_SLEEP},
53 	{"test_copy_from_user_str_dynptr", SETUP_SYSCALL_SLEEP},
54 	{"test_copy_from_user_task_dynptr", SETUP_SYSCALL_SLEEP},
55 	{"test_copy_from_user_task_str_dynptr", SETUP_SYSCALL_SLEEP},
56 };
57 
58 #define PAGE_SIZE_64K 65536
59 
verify_success(const char * prog_name,enum test_setup_type setup_type)60 static void verify_success(const char *prog_name, enum test_setup_type setup_type)
61 {
62 	char user_data[384] = {[0 ... 382] = 'a', '\0'};
63 	struct dynptr_success *skel;
64 	struct bpf_program *prog;
65 	struct bpf_link *link;
66 	int err;
67 
68 	skel = dynptr_success__open();
69 	if (!ASSERT_OK_PTR(skel, "dynptr_success__open"))
70 		return;
71 
72 	skel->bss->pid = getpid();
73 
74 	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
75 	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
76 		goto cleanup;
77 
78 	bpf_program__set_autoload(prog, true);
79 
80 	err = dynptr_success__load(skel);
81 	if (!ASSERT_OK(err, "dynptr_success__load"))
82 		goto cleanup;
83 
84 	skel->bss->user_ptr = user_data;
85 	skel->data->test_len[0] = sizeof(user_data);
86 	memcpy(skel->bss->expected_str, user_data, sizeof(user_data));
87 
88 	switch (setup_type) {
89 	case SETUP_SYSCALL_SLEEP:
90 		link = bpf_program__attach(prog);
91 		if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
92 			goto cleanup;
93 
94 		usleep(1);
95 
96 		bpf_link__destroy(link);
97 		break;
98 	case SETUP_SKB_PROG:
99 	case SETUP_SKB_PROG_NONLINEAR:
100 	{
101 		struct __sk_buff ctx = {};
102 		int prog_fd;
103 		char buf[64];
104 
105 		LIBBPF_OPTS(bpf_test_run_opts, topts,
106 			    .data_in = &pkt_v4,
107 			    .data_size_in = sizeof(pkt_v4),
108 			    .data_out = buf,
109 			    .data_size_out = sizeof(buf),
110 			    .repeat = 1,
111 		);
112 
113 		if (setup_type == SETUP_SKB_PROG_NONLINEAR) {
114 			ctx.data_end = ETH_HLEN + sizeof(struct iphdr);
115 			topts.ctx_in = &ctx;
116 			topts.ctx_size_in = sizeof(ctx);
117 		}
118 
119 		prog_fd = bpf_program__fd(prog);
120 		if (!ASSERT_GE(prog_fd, 0, "prog_fd"))
121 			goto cleanup;
122 
123 		err = bpf_prog_test_run_opts(prog_fd, &topts);
124 
125 		if (!ASSERT_OK(err, "test_run"))
126 			goto cleanup;
127 
128 		break;
129 	}
130 	case SETUP_SKB_PROG_TP:
131 	{
132 		struct __sk_buff skb = {};
133 		struct bpf_object *obj;
134 		int aux_prog_fd;
135 
136 		/* Just use its test_run to trigger kfree_skb tracepoint */
137 		err = bpf_prog_test_load("./test_pkt_access.bpf.o", BPF_PROG_TYPE_SCHED_CLS,
138 					 &obj, &aux_prog_fd);
139 		if (!ASSERT_OK(err, "prog_load sched cls"))
140 			goto cleanup;
141 
142 		LIBBPF_OPTS(bpf_test_run_opts, topts,
143 			    .data_in = &pkt_v4,
144 			    .data_size_in = sizeof(pkt_v4),
145 			    .ctx_in = &skb,
146 			    .ctx_size_in = sizeof(skb),
147 		);
148 
149 		link = bpf_program__attach(prog);
150 		if (!ASSERT_OK_PTR(link, "bpf_program__attach")) {
151 			bpf_object__close(obj);
152 			goto cleanup;
153 		}
154 
155 		err = bpf_prog_test_run_opts(aux_prog_fd, &topts);
156 		bpf_link__destroy(link);
157 		bpf_object__close(obj);
158 
159 		if (!ASSERT_OK(err, "test_run"))
160 			goto cleanup;
161 
162 		break;
163 	}
164 	case SETUP_XDP_PROG:
165 	{
166 		char data[90000];
167 		int err, prog_fd;
168 		LIBBPF_OPTS(bpf_test_run_opts, opts,
169 			    .data_in = &data,
170 			    .repeat = 1,
171 		);
172 
173 		if (getpagesize() == PAGE_SIZE_64K)
174 			opts.data_size_in = sizeof(data);
175 		else
176 			opts.data_size_in = 5000;
177 
178 		prog_fd = bpf_program__fd(prog);
179 		err = bpf_prog_test_run_opts(prog_fd, &opts);
180 
181 		if (!ASSERT_OK(err, "test_run"))
182 			goto cleanup;
183 
184 		break;
185 	}
186 	}
187 
188 	ASSERT_EQ(skel->bss->err, 0, "err");
189 
190 cleanup:
191 	dynptr_success__destroy(skel);
192 }
193 
test_dynptr(void)194 void test_dynptr(void)
195 {
196 	int i;
197 
198 	for (i = 0; i < ARRAY_SIZE(success_tests); i++) {
199 		if (!test__start_subtest(success_tests[i].prog_name))
200 			continue;
201 
202 		verify_success(success_tests[i].prog_name, success_tests[i].type);
203 	}
204 
205 	RUN_TESTS(dynptr_fail);
206 }
207