1 // Tests of SCTP functionality
2 // Requires: libsctp-dev package on Debian Linux, CONFIG_IP_SCTP in kernel config
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <netinet/in.h>
6 #include <netinet/sctp.h>
7 #include <arpa/inet.h>
8 #include <stdio.h>
9
10 #include "syscalls.h"
11 #include "capsicum.h"
12 #include "capsicum-test.h"
13
14 static cap_rights_t r_ro;
15 static cap_rights_t r_wo;
16 static cap_rights_t r_rw;
17 static cap_rights_t r_all;
18 static cap_rights_t r_all_nopeel;
19 #define DO_PEELOFF 0x1A
20 #define DO_TERM 0x1B
21
SctpClient(int port,unsigned char byte)22 static int SctpClient(int port, unsigned char byte) {
23 // Create sockets
24 int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
25 EXPECT_OK(sock);
26 if (sock < 0) return sock;
27 int cap_sock_ro = dup(sock);
28 EXPECT_OK(cap_sock_ro);
29 EXPECT_OK(cap_rights_limit(cap_sock_ro, &r_rw));
30 int cap_sock_rw = dup(sock);
31 EXPECT_OK(cap_sock_rw);
32 EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
33 int cap_sock_all = dup(sock);
34 EXPECT_OK(cap_sock_all);
35 EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
36 close(sock);
37
38 // Send a message. Requires CAP_WRITE and CAP_CONNECT.
39 struct sockaddr_in serv_addr;
40 memset(&serv_addr, 0, sizeof(serv_addr));
41 serv_addr.sin_family = AF_INET;
42 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
43 serv_addr.sin_port = htons(port);
44
45 EXPECT_NOTCAPABLE(sctp_sendmsg(cap_sock_ro, &byte, 1,
46 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
47 0, 0, 1, 0, 0));
48 EXPECT_NOTCAPABLE(sctp_sendmsg(cap_sock_rw, &byte, 1,
49 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
50 0, 0, 1, 0, 0));
51 if (verbose) fprintf(stderr, " [%d]sctp_sendmsg(%02x)\n", getpid_(), byte);
52 EXPECT_OK(sctp_sendmsg(cap_sock_all, &byte, 1,
53 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
54 0, 0, 1, 0, 0));
55 close(cap_sock_ro);
56 close(cap_sock_rw);
57 return cap_sock_all;
58 }
59
60
TEST(Sctp,Socket)61 TEST(Sctp, Socket) {
62 int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
63 if (sock == -1 && errno == EPROTONOSUPPORT) {
64 GTEST_SKIP() << "socket(..., IPPROTO_SCTP) -> EPROTONOSUPPORT";
65 }
66 EXPECT_OK(sock);
67 if (sock < 0) return;
68
69 cap_rights_init(&r_ro, CAP_READ);
70 cap_rights_init(&r_wo, CAP_WRITE);
71 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
72 cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
73 cap_rights_init(&r_all_nopeel, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
74 cap_rights_clear(&r_all_nopeel, CAP_PEELOFF);
75
76 int cap_sock_wo = dup(sock);
77 EXPECT_OK(cap_sock_wo);
78 EXPECT_OK(cap_rights_limit(cap_sock_wo, &r_wo));
79 int cap_sock_rw = dup(sock);
80 EXPECT_OK(cap_sock_rw);
81 EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
82 int cap_sock_all = dup(sock);
83 EXPECT_OK(cap_sock_all);
84 EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
85 int cap_sock_all_nopeel = dup(sock);
86 EXPECT_OK(cap_sock_all_nopeel);
87 EXPECT_OK(cap_rights_limit(cap_sock_all_nopeel, &r_all_nopeel));
88 close(sock);
89
90 struct sockaddr_in addr;
91 memset(&addr, 0, sizeof(addr));
92 addr.sin_family = AF_INET;
93 addr.sin_port = htons(0);
94 addr.sin_addr.s_addr = htonl(INADDR_ANY);
95 socklen_t len = sizeof(addr);
96
97 // Can only bind the fully-capable socket.
98 EXPECT_NOTCAPABLE(bind(cap_sock_rw, (struct sockaddr *)&addr, len));
99 EXPECT_OK(bind(cap_sock_all, (struct sockaddr *)&addr, len));
100
101 EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr *)&addr, &len));
102 int port = ntohs(addr.sin_port);
103
104 // Now we know the port involved, fork off children to run clients.
105 pid_t child1 = fork();
106 if (child1 == 0) {
107 // Child process 1: wait for server setup
108 sleep(1);
109 // Send a message that triggers peeloff
110 int client_sock = SctpClient(port, DO_PEELOFF);
111 sleep(1);
112 close(client_sock);
113 exit(HasFailure());
114 }
115
116 pid_t child2 = fork();
117 if (child2 == 0) {
118 // Child process 2: wait for server setup
119 sleep(2);
120 // Send a message that triggers server exit
121 int client_sock = SctpClient(port, DO_TERM);
122 close(client_sock);
123 exit(HasFailure());
124 }
125
126 // Can only listen on the fully-capable socket.
127 EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
128 EXPECT_OK(listen(cap_sock_all, 3));
129
130 // Can only do socket operations on the fully-capable socket.
131 len = sizeof(addr);
132 EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
133
134 struct sctp_event_subscribe events;
135 memset(&events, 0, sizeof(events));
136 events.sctp_association_event = 1;
137 events.sctp_data_io_event = 1;
138 EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)));
139 len = sizeof(events);
140 EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, &len));
141 memset(&events, 0, sizeof(events));
142 events.sctp_association_event = 1;
143 events.sctp_data_io_event = 1;
144 EXPECT_OK(setsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)));
145 len = sizeof(events);
146 EXPECT_OK(getsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, &len));
147
148 len = sizeof(addr);
149 memset(&addr, 0, sizeof(addr));
150 EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
151 EXPECT_EQ(AF_INET, addr.sin_family);
152 EXPECT_EQ(htons(port), addr.sin_port);
153
154 struct sockaddr_in client_addr;
155 socklen_t addr_len = sizeof(client_addr);
156 unsigned char buffer[1024];
157 struct sctp_sndrcvinfo sri;
158 memset(&sri, 0, sizeof(sri));
159 int flags = 0;
160 EXPECT_NOTCAPABLE(sctp_recvmsg(cap_sock_wo, buffer, sizeof(buffer),
161 (struct sockaddr*)&client_addr, &addr_len,
162 &sri, &flags));
163 while (true) {
164 retry:
165 memset(&sri, 0, sizeof(sri));
166 int len = sctp_recvmsg(cap_sock_rw, buffer, sizeof(buffer),
167 (struct sockaddr*)&client_addr, &addr_len,
168 &sri, &flags);
169 if (len < 0 && errno == EAGAIN) goto retry;
170 EXPECT_OK(len);
171 if (len > 0) {
172 if (verbose) fprintf(stderr, "[%d]sctp_recvmsg(%02x..)", getpid_(), (unsigned)buffer[0]);
173 if (buffer[0] == DO_PEELOFF) {
174 if (verbose) fprintf(stderr, "..peeling off association %08lx\n", (long)sri.sinfo_assoc_id);
175 // Peel off the association. Needs CAP_PEELOFF.
176 int rc1 = sctp_peeloff(cap_sock_all_nopeel, sri.sinfo_assoc_id);
177 EXPECT_NOTCAPABLE(rc1);
178 int rc2 = sctp_peeloff(cap_sock_all, sri.sinfo_assoc_id);
179 EXPECT_OK(rc2);
180 int peeled = std::max(rc1, rc2);
181 if (peeled > 0) {
182 // Peeled off FD should have same rights as original socket.
183 cap_rights_t rights;
184 EXPECT_OK(cap_rights_get(peeled, &rights));
185 EXPECT_RIGHTS_EQ(&r_all, &rights);
186 close(peeled);
187 }
188 } else if (buffer[0] == DO_TERM) {
189 if (verbose) fprintf(stderr, "..terminating server\n");
190 break;
191 }
192 } else if (len < 0) {
193 break;
194 }
195 }
196
197 // Wait for the children.
198 int status;
199 int rc;
200 EXPECT_EQ(child1, waitpid(child1, &status, 0));
201 rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
202 EXPECT_EQ(0, rc);
203 EXPECT_EQ(child2, waitpid(child2, &status, 0));
204 rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
205 EXPECT_EQ(0, rc);
206
207 close(cap_sock_wo);
208 close(cap_sock_rw);
209 close(cap_sock_all);
210 close(cap_sock_all_nopeel);
211 }
212