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