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