]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
scsi: zfcp: Trace when request remove fails after qdio send fails
[linux.git] / tools / testing / selftests / bpf / prog_tests / sockopt_sk.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "cgroup_helpers.h"
4
5 #include <linux/tcp.h>
6 #include "sockopt_sk.skel.h"
7
8 #ifndef SOL_TCP
9 #define SOL_TCP IPPROTO_TCP
10 #endif
11
12 #define SOL_CUSTOM                      0xdeadbeef
13
14 static int getsetsockopt(void)
15 {
16         int fd, err;
17         union {
18                 char u8[4];
19                 __u32 u32;
20                 char cc[16]; /* TCP_CA_NAME_MAX */
21                 struct tcp_zerocopy_receive zc;
22         } buf = {};
23         socklen_t optlen;
24         char *big_buf = NULL;
25
26         fd = socket(AF_INET, SOCK_STREAM, 0);
27         if (fd < 0) {
28                 log_err("Failed to create socket");
29                 return -1;
30         }
31
32         /* IP_TOS - BPF bypass */
33
34         optlen = getpagesize() * 2;
35         big_buf = calloc(1, optlen);
36         if (!big_buf) {
37                 log_err("Couldn't allocate two pages");
38                 goto err;
39         }
40
41         *(int *)big_buf = 0x08;
42         err = setsockopt(fd, SOL_IP, IP_TOS, big_buf, optlen);
43         if (err) {
44                 log_err("Failed to call setsockopt(IP_TOS)");
45                 goto err;
46         }
47
48         memset(big_buf, 0, optlen);
49         optlen = 1;
50         err = getsockopt(fd, SOL_IP, IP_TOS, big_buf, &optlen);
51         if (err) {
52                 log_err("Failed to call getsockopt(IP_TOS)");
53                 goto err;
54         }
55
56         if (*big_buf != 0x08) {
57                 log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
58                         (int)*big_buf);
59                 goto err;
60         }
61
62         /* IP_TTL - EPERM */
63
64         buf.u8[0] = 1;
65         err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
66         if (!err || errno != EPERM) {
67                 log_err("Unexpected success from setsockopt(IP_TTL)");
68                 goto err;
69         }
70
71         /* SOL_CUSTOM - handled by BPF */
72
73         buf.u8[0] = 0x01;
74         err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
75         if (err) {
76                 log_err("Failed to call setsockopt");
77                 goto err;
78         }
79
80         buf.u32 = 0x00;
81         optlen = 4;
82         err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
83         if (err) {
84                 log_err("Failed to call getsockopt");
85                 goto err;
86         }
87
88         if (optlen != 1) {
89                 log_err("Unexpected optlen %d != 1", optlen);
90                 goto err;
91         }
92         if (buf.u8[0] != 0x01) {
93                 log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
94                 goto err;
95         }
96
97         /* IP_FREEBIND - BPF can't access optval past PAGE_SIZE */
98
99         optlen = getpagesize() * 2;
100         memset(big_buf, 0, optlen);
101
102         err = setsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, optlen);
103         if (err != 0) {
104                 log_err("Failed to call setsockopt, ret=%d", err);
105                 goto err;
106         }
107
108         err = getsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, &optlen);
109         if (err != 0) {
110                 log_err("Failed to call getsockopt, ret=%d", err);
111                 goto err;
112         }
113
114         if (optlen != 1 || *(__u8 *)big_buf != 0x55) {
115                 log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
116                         optlen, *(__u8 *)big_buf);
117         }
118
119         /* SO_SNDBUF is overwritten */
120
121         buf.u32 = 0x01010101;
122         err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
123         if (err) {
124                 log_err("Failed to call setsockopt(SO_SNDBUF)");
125                 goto err;
126         }
127
128         buf.u32 = 0x00;
129         optlen = 4;
130         err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
131         if (err) {
132                 log_err("Failed to call getsockopt(SO_SNDBUF)");
133                 goto err;
134         }
135
136         if (buf.u32 != 0x55AA*2) {
137                 log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
138                         buf.u32);
139                 goto err;
140         }
141
142         /* TCP_CONGESTION can extend the string */
143
144         strcpy(buf.cc, "nv");
145         err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
146         if (err) {
147                 log_err("Failed to call setsockopt(TCP_CONGESTION)");
148                 goto err;
149         }
150
151
152         optlen = sizeof(buf.cc);
153         err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
154         if (err) {
155                 log_err("Failed to call getsockopt(TCP_CONGESTION)");
156                 goto err;
157         }
158
159         if (strcmp(buf.cc, "cubic") != 0) {
160                 log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
161                         buf.cc, "cubic");
162                 goto err;
163         }
164
165         /* TCP_ZEROCOPY_RECEIVE triggers */
166         memset(&buf, 0, sizeof(buf));
167         optlen = sizeof(buf.zc);
168         err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
169         if (err) {
170                 log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
171                         err, errno);
172                 goto err;
173         }
174
175         memset(&buf, 0, sizeof(buf));
176         buf.zc.address = 12345; /* Not page aligned. Rejected by tcp_zerocopy_receive() */
177         optlen = sizeof(buf.zc);
178         errno = 0;
179         err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
180         if (errno != EINVAL) {
181                 log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
182                         err, errno);
183                 goto err;
184         }
185
186         free(big_buf);
187         close(fd);
188         return 0;
189 err:
190         free(big_buf);
191         close(fd);
192         return -1;
193 }
194
195 static void run_test(int cgroup_fd)
196 {
197         struct sockopt_sk *skel;
198
199         skel = sockopt_sk__open_and_load();
200         if (!ASSERT_OK_PTR(skel, "skel_load"))
201                 goto cleanup;
202
203         skel->bss->page_size = getpagesize();
204
205         skel->links._setsockopt =
206                 bpf_program__attach_cgroup(skel->progs._setsockopt, cgroup_fd);
207         if (!ASSERT_OK_PTR(skel->links._setsockopt, "setsockopt_link"))
208                 goto cleanup;
209
210         skel->links._getsockopt =
211                 bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
212         if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
213                 goto cleanup;
214
215         ASSERT_OK(getsetsockopt(), "getsetsockopt");
216
217 cleanup:
218         sockopt_sk__destroy(skel);
219 }
220
221 void test_sockopt_sk(void)
222 {
223         int cgroup_fd;
224
225         cgroup_fd = test__join_cgroup("/sockopt_sk");
226         if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /sockopt_sk"))
227                 return;
228
229         run_test(cgroup_fd);
230         close(cgroup_fd);
231 }
This page took 0.047454 seconds and 4 git commands to generate.