Merge branch 'address-masking'
[linux-2.6-microblaze.git] / tools / testing / selftests / bpf / prog_tests / sockopt_multi.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "cgroup_helpers.h"
4
5 #include "sockopt_multi.skel.h"
6
7 static int run_getsockopt_test(struct sockopt_multi *obj, int cg_parent,
8                                int cg_child, int sock_fd)
9 {
10         struct bpf_link *link_parent = NULL;
11         struct bpf_link *link_child = NULL;
12         socklen_t optlen;
13         __u8 buf;
14         int err;
15
16         /* Set IP_TOS to the expected value (0x80). */
17
18         buf = 0x80;
19         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
20         if (err < 0) {
21                 log_err("Failed to call setsockopt(IP_TOS)");
22                 goto detach;
23         }
24
25         buf = 0x00;
26         optlen = 1;
27         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
28         if (err) {
29                 log_err("Failed to call getsockopt(IP_TOS)");
30                 goto detach;
31         }
32
33         if (buf != 0x80) {
34                 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
35                 err = -1;
36                 goto detach;
37         }
38
39         /* Attach child program and make sure it returns new value:
40          * - kernel:      -> 0x80
41          * - child:  0x80 -> 0x90
42          */
43
44         link_child = bpf_program__attach_cgroup(obj->progs._getsockopt_child,
45                                                 cg_child);
46         if (!ASSERT_OK_PTR(link_child, "cg-attach-getsockopt_child"))
47                 goto detach;
48
49         buf = 0x00;
50         optlen = 1;
51         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
52         if (err) {
53                 log_err("Failed to call getsockopt(IP_TOS)");
54                 goto detach;
55         }
56
57         if (buf != 0x90) {
58                 log_err("Unexpected getsockopt 0x%x != 0x90", buf);
59                 err = -1;
60                 goto detach;
61         }
62
63         /* Attach parent program and make sure it returns new value:
64          * - kernel:      -> 0x80
65          * - child:  0x80 -> 0x90
66          * - parent: 0x90 -> 0xA0
67          */
68
69         link_parent = bpf_program__attach_cgroup(obj->progs._getsockopt_parent,
70                                                  cg_parent);
71         if (!ASSERT_OK_PTR(link_parent, "cg-attach-getsockopt_parent"))
72                 goto detach;
73
74         buf = 0x00;
75         optlen = 1;
76         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
77         if (err) {
78                 log_err("Failed to call getsockopt(IP_TOS)");
79                 goto detach;
80         }
81
82         if (buf != 0xA0) {
83                 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
84                 err = -1;
85                 goto detach;
86         }
87
88         /* Setting unexpected initial sockopt should return EPERM:
89          * - kernel: -> 0x40
90          * - child:  unexpected 0x40, EPERM
91          * - parent: unexpected 0x40, EPERM
92          */
93
94         buf = 0x40;
95         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
96         if (err < 0) {
97                 log_err("Failed to call setsockopt(IP_TOS)");
98                 goto detach;
99         }
100
101         buf = 0x00;
102         optlen = 1;
103         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
104         if (!err) {
105                 log_err("Unexpected success from getsockopt(IP_TOS)");
106                 goto detach;
107         }
108
109         /* Detach child program and make sure we still get EPERM:
110          * - kernel: -> 0x40
111          * - parent: unexpected 0x40, EPERM
112          */
113
114         bpf_link__destroy(link_child);
115         link_child = NULL;
116
117         buf = 0x00;
118         optlen = 1;
119         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
120         if (!err) {
121                 log_err("Unexpected success from getsockopt(IP_TOS)");
122                 goto detach;
123         }
124
125         /* Set initial value to the one the parent program expects:
126          * - kernel:      -> 0x90
127          * - parent: 0x90 -> 0xA0
128          */
129
130         buf = 0x90;
131         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
132         if (err < 0) {
133                 log_err("Failed to call setsockopt(IP_TOS)");
134                 goto detach;
135         }
136
137         buf = 0x00;
138         optlen = 1;
139         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
140         if (err) {
141                 log_err("Failed to call getsockopt(IP_TOS)");
142                 goto detach;
143         }
144
145         if (buf != 0xA0) {
146                 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
147                 err = -1;
148                 goto detach;
149         }
150
151 detach:
152         bpf_link__destroy(link_child);
153         bpf_link__destroy(link_parent);
154
155         return err;
156 }
157
158 static int run_setsockopt_test(struct sockopt_multi *obj, int cg_parent,
159                                int cg_child, int sock_fd)
160 {
161         struct bpf_link *link_parent = NULL;
162         struct bpf_link *link_child = NULL;
163         socklen_t optlen;
164         __u8 buf;
165         int err;
166
167         /* Set IP_TOS to the expected value (0x80). */
168
169         buf = 0x80;
170         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
171         if (err < 0) {
172                 log_err("Failed to call setsockopt(IP_TOS)");
173                 goto detach;
174         }
175
176         buf = 0x00;
177         optlen = 1;
178         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
179         if (err) {
180                 log_err("Failed to call getsockopt(IP_TOS)");
181                 goto detach;
182         }
183
184         if (buf != 0x80) {
185                 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
186                 err = -1;
187                 goto detach;
188         }
189
190         /* Attach child program and make sure it adds 0x10. */
191
192         link_child = bpf_program__attach_cgroup(obj->progs._setsockopt,
193                                                 cg_child);
194         if (!ASSERT_OK_PTR(link_child, "cg-attach-setsockopt_child"))
195                 goto detach;
196
197         buf = 0x80;
198         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
199         if (err < 0) {
200                 log_err("Failed to call setsockopt(IP_TOS)");
201                 goto detach;
202         }
203
204         buf = 0x00;
205         optlen = 1;
206         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
207         if (err) {
208                 log_err("Failed to call getsockopt(IP_TOS)");
209                 goto detach;
210         }
211
212         if (buf != 0x80 + 0x10) {
213                 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);
214                 err = -1;
215                 goto detach;
216         }
217
218         /* Attach parent program and make sure it adds another 0x10. */
219
220         link_parent = bpf_program__attach_cgroup(obj->progs._setsockopt,
221                                                  cg_parent);
222         if (!ASSERT_OK_PTR(link_parent, "cg-attach-setsockopt_parent"))
223                 goto detach;
224
225         buf = 0x80;
226         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
227         if (err < 0) {
228                 log_err("Failed to call setsockopt(IP_TOS)");
229                 goto detach;
230         }
231
232         buf = 0x00;
233         optlen = 1;
234         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
235         if (err) {
236                 log_err("Failed to call getsockopt(IP_TOS)");
237                 goto detach;
238         }
239
240         if (buf != 0x80 + 2 * 0x10) {
241                 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);
242                 err = -1;
243                 goto detach;
244         }
245
246 detach:
247         bpf_link__destroy(link_child);
248         bpf_link__destroy(link_parent);
249
250         return err;
251 }
252
253 void test_sockopt_multi(void)
254 {
255         int cg_parent = -1, cg_child = -1;
256         struct sockopt_multi *obj = NULL;
257         int sock_fd = -1;
258
259         cg_parent = test__join_cgroup("/parent");
260         if (!ASSERT_GE(cg_parent, 0, "join_cgroup /parent"))
261                 goto out;
262
263         cg_child = test__join_cgroup("/parent/child");
264         if (!ASSERT_GE(cg_child, 0, "join_cgroup /parent/child"))
265                 goto out;
266
267         obj = sockopt_multi__open_and_load();
268         if (!ASSERT_OK_PTR(obj, "skel-load"))
269                 goto out;
270
271         obj->bss->page_size = sysconf(_SC_PAGESIZE);
272
273         sock_fd = socket(AF_INET, SOCK_STREAM, 0);
274         if (!ASSERT_GE(sock_fd, 0, "socket"))
275                 goto out;
276
277         ASSERT_OK(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd), "getsockopt_test");
278         ASSERT_OK(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd), "setsockopt_test");
279
280 out:
281         close(sock_fd);
282         sockopt_multi__destroy(obj);
283         close(cg_child);
284         close(cg_parent);
285 }