Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/capsicum-test/socket.cc
39475 views
1
// Tests for socket functionality.
2
#include <sys/types.h>
3
#include <sys/socket.h>
4
#include <sys/un.h>
5
#include <netinet/in.h>
6
#include <arpa/inet.h>
7
#include <unistd.h>
8
9
#include <string>
10
11
#include "capsicum.h"
12
#include "syscalls.h"
13
#include "capsicum-test.h"
14
15
TEST(Socket, UnixDomain) {
16
const char* socketName = TmpFile("capsicum-test.socket");
17
unlink(socketName);
18
cap_rights_t r_rw;
19
cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
20
cap_rights_t r_all;
21
cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
22
23
int pipefds[2];
24
EXPECT_EQ(0, pipe(pipefds));
25
pid_t child = fork();
26
if (child == 0) {
27
// Child process: wait for server setup
28
close(pipefds[0]);
29
AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_CHILD_SHOULD_RUN);
30
31
// Create sockets
32
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
33
EXPECT_OK(sock);
34
if (sock < 0) return;
35
36
int cap_sock_rw = dup(sock);
37
EXPECT_OK(cap_sock_rw);
38
EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
39
int cap_sock_all = dup(sock);
40
EXPECT_OK(cap_sock_all);
41
EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
42
EXPECT_OK(close(sock));
43
44
// Connect socket
45
struct sockaddr_un un;
46
memset(&un, 0, sizeof(un));
47
un.sun_family = AF_UNIX;
48
strcpy(un.sun_path, socketName);
49
socklen_t len = sizeof(un);
50
EXPECT_NOTCAPABLE(connect_(cap_sock_rw, (struct sockaddr *)&un, len));
51
EXPECT_OK(connect_(cap_sock_all, (struct sockaddr *)&un, len));
52
53
exit(HasFailure());
54
}
55
56
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
57
EXPECT_OK(sock);
58
if (sock < 0) return;
59
60
int cap_sock_rw = dup(sock);
61
EXPECT_OK(cap_sock_rw);
62
EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
63
int cap_sock_all = dup(sock);
64
EXPECT_OK(cap_sock_all);
65
EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
66
EXPECT_OK(close(sock));
67
68
struct sockaddr_un un;
69
memset(&un, 0, sizeof(un));
70
un.sun_family = AF_UNIX;
71
strcpy(un.sun_path, socketName);
72
socklen_t len = (sizeof(un) - sizeof(un.sun_path) + strlen(un.sun_path));
73
74
// Can only bind the fully-capable socket.
75
EXPECT_NOTCAPABLE(bind_(cap_sock_rw, (struct sockaddr *)&un, len));
76
EXPECT_OK(bind_(cap_sock_all, (struct sockaddr *)&un, len));
77
78
// Can only listen on the fully-capable socket.
79
EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
80
EXPECT_OK(listen(cap_sock_all, 3));
81
82
// Can only do socket operations on the fully-capable socket.
83
len = sizeof(un);
84
EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&un, &len));
85
int value = 0;
86
EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, SOL_SOCKET, SO_DEBUG, &value, sizeof(value)));
87
len = sizeof(value);
88
EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, SOL_SOCKET, SO_DEBUG, &value, &len));
89
90
len = sizeof(un);
91
memset(&un, 0, sizeof(un));
92
EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&un, &len));
93
EXPECT_EQ(AF_UNIX, un.sun_family);
94
EXPECT_EQ(std::string(socketName), std::string(un.sun_path));
95
value = 0;
96
EXPECT_OK(setsockopt(cap_sock_all, SOL_SOCKET, SO_DEBUG, &value, sizeof(value)));
97
len = sizeof(value);
98
EXPECT_OK(getsockopt(cap_sock_all, SOL_SOCKET, SO_DEBUG, &value, &len));
99
100
// Tell the child process that we are ready and accept the incoming connection.
101
EXPECT_OK(close(pipefds[1]));
102
SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_CHILD_SHOULD_RUN);
103
len = sizeof(un);
104
memset(&un, 0, sizeof(un));
105
EXPECT_NOTCAPABLE(accept(cap_sock_rw, (struct sockaddr *)&un, &len));
106
int conn_fd = accept(cap_sock_all, (struct sockaddr *)&un, &len);
107
EXPECT_OK(conn_fd);
108
109
#ifdef CAP_FROM_ACCEPT
110
// New connection should also be a capability.
111
cap_rights_t rights;
112
cap_rights_init(&rights, 0);
113
EXPECT_OK(cap_rights_get(conn_fd, &rights));
114
EXPECT_RIGHTS_IN(&rights, &r_all);
115
#endif
116
117
// Wait for the child.
118
int status;
119
EXPECT_EQ(child, waitpid(child, &status, 0));
120
int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
121
EXPECT_EQ(0, rc);
122
123
close(conn_fd);
124
close(cap_sock_rw);
125
close(cap_sock_all);
126
unlink(socketName);
127
}
128
129
TEST(Socket, TCP) {
130
int sock = socket(AF_INET, SOCK_STREAM, 0);
131
EXPECT_OK(sock);
132
if (sock < 0) return;
133
134
cap_rights_t r_rw;
135
cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
136
cap_rights_t r_all;
137
cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
138
139
int cap_sock_rw = dup(sock);
140
EXPECT_OK(cap_sock_rw);
141
EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
142
int cap_sock_all = dup(sock);
143
EXPECT_OK(cap_sock_all);
144
EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
145
close(sock);
146
147
struct sockaddr_in addr;
148
memset(&addr, 0, sizeof(addr));
149
addr.sin_family = AF_INET;
150
addr.sin_port = htons(0);
151
addr.sin_addr.s_addr = htonl(INADDR_ANY);
152
socklen_t len = sizeof(addr);
153
154
// Can only bind the fully-capable socket.
155
EXPECT_NOTCAPABLE(bind_(cap_sock_rw, (struct sockaddr *)&addr, len));
156
EXPECT_OK(bind_(cap_sock_all, (struct sockaddr *)&addr, len));
157
158
getsockname(cap_sock_all, (struct sockaddr *)&addr, &len);
159
int port = ntohs(addr.sin_port);
160
161
int pipefds[2];
162
EXPECT_EQ(0, pipe(pipefds));
163
// Now we know the port involved, fork off a child.
164
pid_t child = fork();
165
if (child == 0) {
166
// Child process: wait for server setup
167
close(pipefds[0]);
168
AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_CHILD_SHOULD_RUN);
169
170
// Create sockets
171
int sock = socket(AF_INET, SOCK_STREAM, 0);
172
EXPECT_OK(sock);
173
if (sock < 0) return;
174
int cap_sock_rw = dup(sock);
175
EXPECT_OK(cap_sock_rw);
176
EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
177
int cap_sock_all = dup(sock);
178
EXPECT_OK(cap_sock_all);
179
EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
180
close(sock);
181
182
// Connect socket
183
struct sockaddr_in addr;
184
memset(&addr, 0, sizeof(addr));
185
addr.sin_family = AF_INET;
186
addr.sin_port = htons(port); // Pick unused port
187
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
188
socklen_t len = sizeof(addr);
189
EXPECT_NOTCAPABLE(connect_(cap_sock_rw, (struct sockaddr *)&addr, len));
190
EXPECT_OK(connect_(cap_sock_all, (struct sockaddr *)&addr, len));
191
192
exit(HasFailure());
193
}
194
195
// Can only listen on the fully-capable socket.
196
EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
197
EXPECT_OK(listen(cap_sock_all, 3));
198
199
// Can only do socket operations on the fully-capable socket.
200
len = sizeof(addr);
201
EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
202
int value = 1;
203
EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
204
len = sizeof(value);
205
EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, &len));
206
207
len = sizeof(addr);
208
memset(&addr, 0, sizeof(addr));
209
EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
210
EXPECT_EQ(AF_INET, addr.sin_family);
211
EXPECT_EQ(htons(port), addr.sin_port);
212
value = 0;
213
EXPECT_OK(setsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
214
len = sizeof(value);
215
EXPECT_OK(getsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, &len));
216
217
// Tell the child process that we are ready and accept the incoming connection.
218
EXPECT_OK(close(pipefds[1]));
219
SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_CHILD_SHOULD_RUN);
220
len = sizeof(addr);
221
memset(&addr, 0, sizeof(addr));
222
EXPECT_NOTCAPABLE(accept(cap_sock_rw, (struct sockaddr *)&addr, &len));
223
int conn_fd = accept(cap_sock_all, (struct sockaddr *)&addr, &len);
224
EXPECT_OK(conn_fd);
225
226
#ifdef CAP_FROM_ACCEPT
227
// New connection should also be a capability.
228
cap_rights_t rights;
229
cap_rights_init(&rights, 0);
230
EXPECT_OK(cap_rights_get(conn_fd, &rights));
231
EXPECT_RIGHTS_IN(&rights, &r_all);
232
#endif
233
234
// Wait for the child.
235
int status;
236
EXPECT_EQ(child, waitpid(child, &status, 0));
237
int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
238
EXPECT_EQ(0, rc);
239
240
close(conn_fd);
241
close(cap_sock_rw);
242
close(cap_sock_all);
243
}
244
245
TEST(Socket, UDP) {
246
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
247
EXPECT_OK(sock);
248
if (sock < 0) return;
249
250
cap_rights_t r_rw;
251
cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
252
cap_rights_t r_all;
253
cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
254
cap_rights_t r_connect;
255
cap_rights_init(&r_connect, CAP_READ, CAP_WRITE, CAP_CONNECT);
256
257
int cap_sock_rw = dup(sock);
258
EXPECT_OK(cap_sock_rw);
259
EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
260
int cap_sock_all = dup(sock);
261
EXPECT_OK(cap_sock_all);
262
EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
263
close(sock);
264
265
struct sockaddr_in addr;
266
memset(&addr, 0, sizeof(addr));
267
addr.sin_family = AF_INET;
268
addr.sin_port = htons(0);
269
addr.sin_addr.s_addr = htonl(INADDR_ANY);
270
socklen_t len = sizeof(addr);
271
272
// Can only bind the fully-capable socket.
273
EXPECT_NOTCAPABLE(bind_(cap_sock_rw, (struct sockaddr *)&addr, len));
274
EXPECT_OK(bind_(cap_sock_all, (struct sockaddr *)&addr, len));
275
getsockname(cap_sock_all, (struct sockaddr *)&addr, &len);
276
int port = ntohs(addr.sin_port);
277
278
// Can only do socket operations on the fully-capable socket.
279
len = sizeof(addr);
280
EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
281
int value = 1;
282
EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
283
len = sizeof(value);
284
EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, SOL_SOCKET, SO_REUSEPORT, &value, &len));
285
286
len = sizeof(addr);
287
memset(&addr, 0, sizeof(addr));
288
EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
289
EXPECT_EQ(AF_INET, addr.sin_family);
290
EXPECT_EQ(htons(port), addr.sin_port);
291
value = 1;
292
EXPECT_OK(setsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)));
293
len = sizeof(value);
294
EXPECT_OK(getsockopt(cap_sock_all, SOL_SOCKET, SO_REUSEPORT, &value, &len));
295
296
pid_t child = fork();
297
if (child == 0) {
298
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
299
EXPECT_OK(sock);
300
int cap_sock_rw = dup(sock);
301
EXPECT_OK(cap_sock_rw);
302
EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
303
int cap_sock_connect = dup(sock);
304
EXPECT_OK(cap_sock_connect);
305
EXPECT_OK(cap_rights_limit(cap_sock_connect, &r_connect));
306
close(sock);
307
308
// Can only sendmsg(2) to an address over a socket with CAP_CONNECT.
309
unsigned char buffer[256];
310
struct iovec iov;
311
memset(&iov, 0, sizeof(iov));
312
iov.iov_base = buffer;
313
iov.iov_len = sizeof(buffer);
314
315
struct msghdr mh;
316
memset(&mh, 0, sizeof(mh));
317
mh.msg_iov = &iov;
318
mh.msg_iovlen = 1;
319
320
struct sockaddr_in addr;
321
memset(&addr, 0, sizeof(addr));
322
addr.sin_family = AF_INET;
323
addr.sin_port = htons(port);
324
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
325
mh.msg_name = &addr;
326
mh.msg_namelen = sizeof(addr);
327
328
EXPECT_NOTCAPABLE(sendmsg(cap_sock_rw, &mh, 0));
329
EXPECT_OK(sendmsg(cap_sock_connect, &mh, 0));
330
331
#ifdef HAVE_SEND_RECV_MMSG
332
struct mmsghdr mv;
333
memset(&mv, 0, sizeof(mv));
334
memcpy(&mv.msg_hdr, &mh, sizeof(struct msghdr));
335
EXPECT_NOTCAPABLE(sendmmsg(cap_sock_rw, &mv, 1, 0));
336
EXPECT_OK(sendmmsg(cap_sock_connect, &mv, 1, 0));
337
#endif
338
close(cap_sock_rw);
339
close(cap_sock_connect);
340
exit(HasFailure());
341
}
342
// Wait for the child.
343
int status;
344
EXPECT_EQ(child, waitpid(child, &status, 0));
345
int rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
346
EXPECT_EQ(0, rc);
347
348
close(cap_sock_rw);
349
close(cap_sock_all);
350
}
351
352