xref: /freebsd/contrib/capsicum-test/capability-fd-pair.cc (revision 9a696dc6bb0e8e783dfd169c8299e1f33aac2935)
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 
TEST(CapabilityPair,sendfile)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
TEST(CapabilityPair,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
TEST(CapabilityPair,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.
TEST(CapabilityPair,vmsplice)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