1
2
3#include <errno.h>
4#include <stdio.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <netinet/in.h>
9
10#include <linux/filter.h>
11#include <bpf/bpf.h>
12#include <bpf/libbpf.h>
13
14#include "bpf_rlimit.h"
15#include "bpf_util.h"
16#include "cgroup_helpers.h"
17
18#define CG_PATH "/sockopt"
19
20#define SOL_CUSTOM 0xdeadbeef
21
22static int getsetsockopt(void)
23{
24 int fd, err;
25 union {
26 char u8[4];
27 __u32 u32;
28 } buf = {};
29 socklen_t optlen;
30
31 fd = socket(AF_INET, SOCK_STREAM, 0);
32 if (fd < 0) {
33 log_err("Failed to create socket");
34 return -1;
35 }
36
37
38
39 buf.u8[0] = 0x08;
40 err = setsockopt(fd, SOL_IP, IP_TOS, &buf, 1);
41 if (err) {
42 log_err("Failed to call setsockopt(IP_TOS)");
43 goto err;
44 }
45
46 buf.u8[0] = 0x00;
47 optlen = 1;
48 err = getsockopt(fd, SOL_IP, IP_TOS, &buf, &optlen);
49 if (err) {
50 log_err("Failed to call getsockopt(IP_TOS)");
51 goto err;
52 }
53
54 if (buf.u8[0] != 0x08) {
55 log_err("Unexpected getsockopt(IP_TOS) buf[0] 0x%02x != 0x08",
56 buf.u8[0]);
57 goto err;
58 }
59
60
61
62 buf.u8[0] = 1;
63 err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
64 if (!err || errno != EPERM) {
65 log_err("Unexpected success from setsockopt(IP_TTL)");
66 goto err;
67 }
68
69
70
71 buf.u8[0] = 0x01;
72 err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
73 if (err) {
74 log_err("Failed to call setsockopt");
75 goto err;
76 }
77
78 buf.u32 = 0x00;
79 optlen = 4;
80 err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
81 if (err) {
82 log_err("Failed to call getsockopt");
83 goto err;
84 }
85
86 if (optlen != 1) {
87 log_err("Unexpected optlen %d != 1", optlen);
88 goto err;
89 }
90 if (buf.u8[0] != 0x01) {
91 log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
92 goto err;
93 }
94
95
96
97 buf.u32 = 0x01010101;
98 err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
99 if (err) {
100 log_err("Failed to call setsockopt(SO_SNDBUF)");
101 goto err;
102 }
103
104 buf.u32 = 0x00;
105 optlen = 4;
106 err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
107 if (err) {
108 log_err("Failed to call getsockopt(SO_SNDBUF)");
109 goto err;
110 }
111
112 if (buf.u32 != 0x55AA*2) {
113 log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
114 buf.u32);
115 goto err;
116 }
117
118 close(fd);
119 return 0;
120err:
121 close(fd);
122 return -1;
123}
124
125static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
126{
127 enum bpf_attach_type attach_type;
128 enum bpf_prog_type prog_type;
129 struct bpf_program *prog;
130 int err;
131
132 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
133 if (err) {
134 log_err("Failed to deduct types for %s BPF program", title);
135 return -1;
136 }
137
138 prog = bpf_object__find_program_by_title(obj, title);
139 if (!prog) {
140 log_err("Failed to find %s BPF program", title);
141 return -1;
142 }
143
144 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
145 attach_type, 0);
146 if (err) {
147 log_err("Failed to attach %s BPF program", title);
148 return -1;
149 }
150
151 return 0;
152}
153
154static int run_test(int cgroup_fd)
155{
156 struct bpf_prog_load_attr attr = {
157 .file = "./sockopt_sk.o",
158 };
159 struct bpf_object *obj;
160 int ignored;
161 int err;
162
163 err = bpf_prog_load_xattr(&attr, &obj, &ignored);
164 if (err) {
165 log_err("Failed to load BPF object");
166 return -1;
167 }
168
169 err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt");
170 if (err)
171 goto close_bpf_object;
172
173 err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt");
174 if (err)
175 goto close_bpf_object;
176
177 err = getsetsockopt();
178
179close_bpf_object:
180 bpf_object__close(obj);
181 return err;
182}
183
184int main(int args, char **argv)
185{
186 int cgroup_fd;
187 int err = EXIT_SUCCESS;
188
189 if (setup_cgroup_environment())
190 goto cleanup_obj;
191
192 cgroup_fd = create_and_get_cgroup(CG_PATH);
193 if (cgroup_fd < 0)
194 goto cleanup_cgroup_env;
195
196 if (join_cgroup(CG_PATH))
197 goto cleanup_cgroup;
198
199 if (run_test(cgroup_fd))
200 err = EXIT_FAILURE;
201
202 printf("test_sockopt_sk: %s\n",
203 err == EXIT_SUCCESS ? "PASSED" : "FAILED");
204
205cleanup_cgroup:
206 close(cgroup_fd);
207cleanup_cgroup_env:
208 cleanup_cgroup_environment();
209cleanup_obj:
210 return err;
211}
212