1 // Tests involving 2 capability file descriptors. 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <fcntl.h> 5 6 #include "capsicum.h" 7 #include "syscalls.h" 8 #include "capsicum-test.h" 9 10 TEST(CapabilityPair, sendfile) { 11 int in_fd = open(TmpFile("cap_sendfile_in"), O_CREAT|O_RDWR, 0644); 12 EXPECT_OK(write(in_fd, "1234", 4)); 13 // Output fd for sendfile must be a stream socket in FreeBSD. 14 int sock_fds[2]; 15 EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds)); 16 17 cap_rights_t r_rs; 18 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); 19 cap_rights_t r_ws; 20 cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK); 21 22 int cap_in_ro = dup(in_fd); 23 EXPECT_OK(cap_in_ro); 24 EXPECT_OK(cap_rights_limit(cap_in_ro, &r_rs)); 25 int cap_in_wo = dup(in_fd); 26 EXPECT_OK(cap_in_wo); 27 EXPECT_OK(cap_rights_limit(cap_in_wo, &r_ws)); 28 int cap_out_ro = dup(sock_fds[0]); 29 EXPECT_OK(cap_out_ro); 30 EXPECT_OK(cap_rights_limit(cap_out_ro, &r_rs)); 31 int cap_out_wo = dup(sock_fds[0]); 32 EXPECT_OK(cap_out_wo); 33 EXPECT_OK(cap_rights_limit(cap_out_wo, &r_ws)); 34 35 off_t offset = 0; 36 EXPECT_NOTCAPABLE(sendfile_(cap_out_ro, cap_in_ro, &offset, 4)); 37 EXPECT_NOTCAPABLE(sendfile_(cap_out_wo, cap_in_wo, &offset, 4)); 38 EXPECT_OK(sendfile_(cap_out_wo, cap_in_ro, &offset, 4)); 39 40 close(cap_in_ro); 41 close(cap_in_wo); 42 close(cap_out_ro); 43 close(cap_out_wo); 44 close(in_fd); 45 close(sock_fds[0]); 46 close(sock_fds[1]); 47 unlink(TmpFile("cap_sendfile_in")); 48 } 49 50 #ifdef HAVE_TEE 51 TEST(CapabilityPair, tee) { 52 int pipe1_fds[2]; 53 EXPECT_OK(pipe2(pipe1_fds, O_NONBLOCK)); 54 int pipe2_fds[2]; 55 EXPECT_OK(pipe2(pipe2_fds, O_NONBLOCK)); 56 57 // Put some data into pipe1. 58 unsigned char buffer[4] = {1, 2, 3, 4}; 59 EXPECT_OK(write(pipe1_fds[1], buffer, 4)); 60 61 cap_rights_t r_ro; 62 cap_rights_init(&r_ro, CAP_READ); 63 cap_rights_t r_wo; 64 cap_rights_init(&r_wo, CAP_WRITE); 65 cap_rights_t r_rw; 66 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE); 67 68 // Various attempts to tee into pipe2. 69 int cap_in_wo = dup(pipe1_fds[0]); 70 EXPECT_OK(cap_in_wo); 71 EXPECT_OK(cap_rights_limit(cap_in_wo, &r_wo)); 72 int cap_in_rw = dup(pipe1_fds[0]); 73 EXPECT_OK(cap_in_rw); 74 EXPECT_OK(cap_rights_limit(cap_in_rw, &r_rw)); 75 int cap_out_ro = dup(pipe2_fds[1]); 76 EXPECT_OK(cap_out_ro); 77 EXPECT_OK(cap_rights_limit(cap_out_ro, &r_ro)); 78 int cap_out_rw = dup(pipe2_fds[1]); 79 EXPECT_OK(cap_out_rw); 80 EXPECT_OK(cap_rights_limit(cap_out_rw, &r_rw)); 81 82 EXPECT_NOTCAPABLE(tee(cap_in_wo, cap_out_rw, 4, SPLICE_F_NONBLOCK)); 83 EXPECT_NOTCAPABLE(tee(cap_in_rw, cap_out_ro, 4, SPLICE_F_NONBLOCK)); 84 EXPECT_OK(tee(cap_in_rw, cap_out_rw, 4, SPLICE_F_NONBLOCK)); 85 86 close(cap_in_wo); 87 close(cap_in_rw); 88 close(cap_out_ro); 89 close(cap_out_rw); 90 close(pipe1_fds[0]); 91 close(pipe1_fds[1]); 92 close(pipe2_fds[0]); 93 close(pipe2_fds[1]); 94 } 95 #endif 96 97 #ifdef HAVE_SPLICE 98 TEST(CapabilityPair, splice) { 99 int pipe1_fds[2]; 100 EXPECT_OK(pipe2(pipe1_fds, O_NONBLOCK)); 101 int pipe2_fds[2]; 102 EXPECT_OK(pipe2(pipe2_fds, O_NONBLOCK)); 103 104 // Put some data into pipe1. 105 unsigned char buffer[4] = {1, 2, 3, 4}; 106 EXPECT_OK(write(pipe1_fds[1], buffer, 4)); 107 108 cap_rights_t r_ro; 109 cap_rights_init(&r_ro, CAP_READ); 110 cap_rights_t r_wo; 111 cap_rights_init(&r_wo, CAP_WRITE); 112 cap_rights_t r_rs; 113 cap_rights_init(&r_rs, CAP_READ, CAP_SEEK); 114 cap_rights_t r_ws; 115 cap_rights_init(&r_ws, CAP_WRITE, CAP_SEEK); 116 117 // Various attempts to splice. 118 int cap_in_wo = dup(pipe1_fds[0]); 119 EXPECT_OK(cap_in_wo); 120 EXPECT_OK(cap_rights_limit(cap_in_wo, &r_wo)); 121 int cap_in_ro = dup(pipe1_fds[0]); 122 EXPECT_OK(cap_in_ro); 123 EXPECT_OK(cap_rights_limit(cap_in_ro, &r_ro)); 124 int cap_in_ro_seek = dup(pipe1_fds[0]); 125 EXPECT_OK(cap_in_ro_seek); 126 EXPECT_OK(cap_rights_limit(cap_in_ro_seek, &r_rs)); 127 int cap_out_wo = dup(pipe2_fds[1]); 128 EXPECT_OK(cap_out_wo); 129 EXPECT_OK(cap_rights_limit(cap_out_wo, &r_wo)); 130 int cap_out_ro = dup(pipe2_fds[1]); 131 EXPECT_OK(cap_out_ro); 132 EXPECT_OK(cap_rights_limit(cap_out_ro, &r_ro)); 133 int cap_out_wo_seek = dup(pipe2_fds[1]); 134 EXPECT_OK(cap_out_wo_seek); 135 EXPECT_OK(cap_rights_limit(cap_out_wo_seek, &r_ws)); 136 137 EXPECT_NOTCAPABLE(splice(cap_in_ro, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK)); 138 EXPECT_NOTCAPABLE(splice(cap_in_wo, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK)); 139 EXPECT_NOTCAPABLE(splice(cap_in_ro_seek, NULL, cap_out_ro, NULL, 4, SPLICE_F_NONBLOCK)); 140 EXPECT_NOTCAPABLE(splice(cap_in_ro_seek, NULL, cap_out_wo, NULL, 4, SPLICE_F_NONBLOCK)); 141 EXPECT_OK(splice(cap_in_ro_seek, NULL, cap_out_wo_seek, NULL, 4, SPLICE_F_NONBLOCK)); 142 143 close(cap_in_wo); 144 close(cap_in_ro); 145 close(cap_in_ro_seek); 146 close(cap_out_wo); 147 close(cap_out_ro); 148 close(cap_out_wo_seek); 149 close(pipe1_fds[0]); 150 close(pipe1_fds[1]); 151 close(pipe2_fds[0]); 152 close(pipe2_fds[1]); 153 } 154 #endif 155 156 #ifdef HAVE_VMSPLICE 157 // Although it only involves a single file descriptor, test vmsplice(2) here too. 158 TEST(CapabilityPair, vmsplice) { 159 int pipe_fds[2]; 160 EXPECT_OK(pipe2(pipe_fds, O_NONBLOCK)); 161 162 cap_rights_t r_ro; 163 cap_rights_init(&r_ro, CAP_READ); 164 cap_rights_t r_rw; 165 cap_rights_init(&r_rw, CAP_READ, CAP_WRITE); 166 167 int cap_ro = dup(pipe_fds[1]); 168 EXPECT_OK(cap_ro); 169 EXPECT_OK(cap_rights_limit(cap_ro, &r_ro)); 170 int cap_rw = dup(pipe_fds[1]); 171 EXPECT_OK(cap_rw); 172 EXPECT_OK(cap_rights_limit(cap_rw, &r_rw)); 173 174 unsigned char buffer[4] = {1, 2, 3, 4}; 175 struct iovec iov; 176 memset(&iov, 0, sizeof(iov)); 177 iov.iov_base = buffer; 178 iov.iov_len = sizeof(buffer); 179 180 EXPECT_NOTCAPABLE(vmsplice(cap_ro, &iov, 1, SPLICE_F_NONBLOCK)); 181 EXPECT_OK(vmsplice(cap_rw, &iov, 1, SPLICE_F_NONBLOCK)); 182 183 close(cap_ro); 184 close(cap_rw); 185 close(pipe_fds[0]); 186 close(pipe_fds[1]); 187 } 188 #endif 189