1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "cgroup_helpers.h"
5 #define SOL_CUSTOM 0xdeadbeef
7 static int getsetsockopt(void)
13 char cc
[16]; /* TCP_CA_NAME_MAX */
18 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
20 log_err("Failed to create socket");
24 /* IP_TOS - BPF bypass */
26 optlen
= getpagesize() * 2;
27 big_buf
= calloc(1, optlen
);
29 log_err("Couldn't allocate two pages");
33 *(int *)big_buf
= 0x08;
34 err
= setsockopt(fd
, SOL_IP
, IP_TOS
, big_buf
, optlen
);
36 log_err("Failed to call setsockopt(IP_TOS)");
40 memset(big_buf
, 0, optlen
);
42 err
= getsockopt(fd
, SOL_IP
, IP_TOS
, big_buf
, &optlen
);
44 log_err("Failed to call getsockopt(IP_TOS)");
48 if (*big_buf
!= 0x08) {
49 log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
57 err
= setsockopt(fd
, SOL_IP
, IP_TTL
, &buf
, 1);
58 if (!err
|| errno
!= EPERM
) {
59 log_err("Unexpected success from setsockopt(IP_TTL)");
63 /* SOL_CUSTOM - handled by BPF */
66 err
= setsockopt(fd
, SOL_CUSTOM
, 0, &buf
, 1);
68 log_err("Failed to call setsockopt");
74 err
= getsockopt(fd
, SOL_CUSTOM
, 0, &buf
, &optlen
);
76 log_err("Failed to call getsockopt");
81 log_err("Unexpected optlen %d != 1", optlen
);
84 if (buf
.u8
[0] != 0x01) {
85 log_err("Unexpected buf[0] 0x%02x != 0x01", buf
.u8
[0]);
89 /* IP_FREEBIND - BPF can't access optval past PAGE_SIZE */
91 optlen
= getpagesize() * 2;
92 memset(big_buf
, 0, optlen
);
94 err
= setsockopt(fd
, SOL_IP
, IP_FREEBIND
, big_buf
, optlen
);
96 log_err("Failed to call setsockopt, ret=%d", err
);
100 err
= getsockopt(fd
, SOL_IP
, IP_FREEBIND
, big_buf
, &optlen
);
102 log_err("Failed to call getsockopt, ret=%d", err
);
106 if (optlen
!= 1 || *(__u8
*)big_buf
!= 0x55) {
107 log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
108 optlen
, *(__u8
*)big_buf
);
111 /* SO_SNDBUF is overwritten */
113 buf
.u32
= 0x01010101;
114 err
= setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &buf
, 4);
116 log_err("Failed to call setsockopt(SO_SNDBUF)");
122 err
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &buf
, &optlen
);
124 log_err("Failed to call getsockopt(SO_SNDBUF)");
128 if (buf
.u32
!= 0x55AA*2) {
129 log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
134 /* TCP_CONGESTION can extend the string */
136 strcpy(buf
.cc
, "nv");
137 err
= setsockopt(fd
, SOL_TCP
, TCP_CONGESTION
, &buf
, strlen("nv"));
139 log_err("Failed to call setsockopt(TCP_CONGESTION)");
144 optlen
= sizeof(buf
.cc
);
145 err
= getsockopt(fd
, SOL_TCP
, TCP_CONGESTION
, &buf
, &optlen
);
147 log_err("Failed to call getsockopt(TCP_CONGESTION)");
151 if (strcmp(buf
.cc
, "cubic") != 0) {
152 log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
166 static int prog_attach(struct bpf_object
*obj
, int cgroup_fd
, const char *title
)
168 enum bpf_attach_type attach_type
;
169 enum bpf_prog_type prog_type
;
170 struct bpf_program
*prog
;
173 err
= libbpf_prog_type_by_name(title
, &prog_type
, &attach_type
);
175 log_err("Failed to deduct types for %s BPF program", title
);
179 prog
= bpf_object__find_program_by_title(obj
, title
);
181 log_err("Failed to find %s BPF program", title
);
185 err
= bpf_prog_attach(bpf_program__fd(prog
), cgroup_fd
,
188 log_err("Failed to attach %s BPF program", title
);
195 static void run_test(int cgroup_fd
)
197 struct bpf_prog_load_attr attr
= {
198 .file
= "./sockopt_sk.o",
200 struct bpf_object
*obj
;
204 err
= bpf_prog_load_xattr(&attr
, &obj
, &ignored
);
208 err
= prog_attach(obj
, cgroup_fd
, "cgroup/getsockopt");
210 goto close_bpf_object
;
212 err
= prog_attach(obj
, cgroup_fd
, "cgroup/setsockopt");
214 goto close_bpf_object
;
216 CHECK_FAIL(getsetsockopt());
219 bpf_object__close(obj
);
222 void test_sockopt_sk(void)
226 cgroup_fd
= test__join_cgroup("/sockopt_sk");
227 if (CHECK_FAIL(cgroup_fd
< 0))