1*62d3f57cSMariusz Zaborski #include <sys/types.h>
2*62d3f57cSMariusz Zaborski #include <fcntl.h>
3*62d3f57cSMariusz Zaborski
4*62d3f57cSMariusz Zaborski #include <string>
5*62d3f57cSMariusz Zaborski
6*62d3f57cSMariusz Zaborski #include "capsicum.h"
7*62d3f57cSMariusz Zaborski #include "capsicum-test.h"
8*62d3f57cSMariusz Zaborski #include "syscalls.h"
9*62d3f57cSMariusz Zaborski
10*62d3f57cSMariusz Zaborski #define TOPDIR "cap_copy_file_range"
11*62d3f57cSMariusz Zaborski #define INFILE "infile"
12*62d3f57cSMariusz Zaborski #define OUTFILE "outfile"
13*62d3f57cSMariusz Zaborski
14*62d3f57cSMariusz Zaborski /* Test that copy_file_range() checks capabilities correctly.
15*62d3f57cSMariusz Zaborski * When used without offset arguments, copy_file_range() should
16*62d3f57cSMariusz Zaborski * require only CAP_READ on the source and CAP_WRITE on the destination
17*62d3f57cSMariusz Zaborski * file descriptors, respectively.
18*62d3f57cSMariusz Zaborski * When used with offset arguments, copy_file_range() should
19*62d3f57cSMariusz Zaborski * additionally require CAP_SEEK.
20*62d3f57cSMariusz Zaborski */
21*62d3f57cSMariusz Zaborski class CopyFileRangeTest : public ::testing::Test {
22*62d3f57cSMariusz Zaborski public:
CopyFileRangeTest()23*62d3f57cSMariusz Zaborski CopyFileRangeTest() {
24*62d3f57cSMariusz Zaborski int rc = mkdir(TmpFile(TOPDIR), 0755);
25*62d3f57cSMariusz Zaborski EXPECT_OK(rc);
26*62d3f57cSMariusz Zaborski if (rc < 0) {
27*62d3f57cSMariusz Zaborski EXPECT_EQ(EEXIST, errno);
28*62d3f57cSMariusz Zaborski }
29*62d3f57cSMariusz Zaborski wd_ = open(TmpFile(TOPDIR), O_DIRECTORY);
30*62d3f57cSMariusz Zaborski EXPECT_OK(wd_);
31*62d3f57cSMariusz Zaborski CreateFile(TmpFile(TOPDIR "/" INFILE));
32*62d3f57cSMariusz Zaborski CreateFile(TmpFile(TOPDIR "/" OUTFILE));
33*62d3f57cSMariusz Zaborski }
~CopyFileRangeTest()34*62d3f57cSMariusz Zaborski ~CopyFileRangeTest() {
35*62d3f57cSMariusz Zaborski close(wd_);
36*62d3f57cSMariusz Zaborski unlink(TmpFile(TOPDIR "/" INFILE));
37*62d3f57cSMariusz Zaborski unlink(TmpFile(TOPDIR "/" OUTFILE));
38*62d3f57cSMariusz Zaborski rmdir(TmpFile(TOPDIR));
39*62d3f57cSMariusz Zaborski }
40*62d3f57cSMariusz Zaborski
41*62d3f57cSMariusz Zaborski private:
CreateFile(const char * filename)42*62d3f57cSMariusz Zaborski void CreateFile(const char *filename) {
43*62d3f57cSMariusz Zaborski int fd = open(filename, O_CREAT|O_RDWR, 0644);
44*62d3f57cSMariusz Zaborski const char *contents = "lorem ipsum dolor sit amet";
45*62d3f57cSMariusz Zaborski EXPECT_OK(fd);
46*62d3f57cSMariusz Zaborski for (int i = 0; i < 100; i++) {
47*62d3f57cSMariusz Zaborski EXPECT_OK(write(fd, contents, strlen(contents)));
48*62d3f57cSMariusz Zaborski }
49*62d3f57cSMariusz Zaborski close(fd);
50*62d3f57cSMariusz Zaborski }
51*62d3f57cSMariusz Zaborski
52*62d3f57cSMariusz Zaborski protected:
53*62d3f57cSMariusz Zaborski int wd_;
54*62d3f57cSMariusz Zaborski
openInFile(cap_rights_t * rights)55*62d3f57cSMariusz Zaborski int openInFile(cap_rights_t *rights) {
56*62d3f57cSMariusz Zaborski int fd = openat(wd_, INFILE, O_RDONLY);
57*62d3f57cSMariusz Zaborski EXPECT_OK(fd);
58*62d3f57cSMariusz Zaborski EXPECT_OK(cap_rights_limit(fd, rights));
59*62d3f57cSMariusz Zaborski return fd;
60*62d3f57cSMariusz Zaborski }
openOutFile(cap_rights_t * rights)61*62d3f57cSMariusz Zaborski int openOutFile(cap_rights_t *rights) {
62*62d3f57cSMariusz Zaborski int fd = openat(wd_, OUTFILE, O_WRONLY);
63*62d3f57cSMariusz Zaborski EXPECT_OK(fd);
64*62d3f57cSMariusz Zaborski EXPECT_OK(cap_rights_limit(fd, rights));
65*62d3f57cSMariusz Zaborski return fd;
66*62d3f57cSMariusz Zaborski }
67*62d3f57cSMariusz Zaborski };
68*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,WriteReadNeg)69*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, WriteReadNeg) {
70*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
71*62d3f57cSMariusz Zaborski
72*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_WRITE);
73*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_READ);
74*62d3f57cSMariusz Zaborski
75*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
76*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
77*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
78*62d3f57cSMariusz Zaborski
79*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
80*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
81*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
82*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
83*62d3f57cSMariusz Zaborski off_in = 20;
84*62d3f57cSMariusz Zaborski off_out = 20;
85*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
86*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
87*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
88*62d3f57cSMariusz Zaborski close(fd_in);
89*62d3f57cSMariusz Zaborski close(fd_out);
90*62d3f57cSMariusz Zaborski }
91*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,ReadReadNeg)92*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, ReadReadNeg) {
93*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
94*62d3f57cSMariusz Zaborski
95*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_READ);
96*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_READ);
97*62d3f57cSMariusz Zaborski
98*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
99*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
100*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
101*62d3f57cSMariusz Zaborski
102*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
103*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
104*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
105*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
106*62d3f57cSMariusz Zaborski off_in = 20;
107*62d3f57cSMariusz Zaborski off_out = 20;
108*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
109*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
110*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
111*62d3f57cSMariusz Zaborski close(fd_in);
112*62d3f57cSMariusz Zaborski close(fd_out);
113*62d3f57cSMariusz Zaborski }
114*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,WriteWriteNeg)115*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, WriteWriteNeg) {
116*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
117*62d3f57cSMariusz Zaborski
118*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_WRITE);
119*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_WRITE);
120*62d3f57cSMariusz Zaborski
121*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
122*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
123*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
124*62d3f57cSMariusz Zaborski
125*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
126*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
127*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
128*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
129*62d3f57cSMariusz Zaborski off_in = 20;
130*62d3f57cSMariusz Zaborski off_out = 20;
131*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
132*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
133*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
134*62d3f57cSMariusz Zaborski close(fd_in);
135*62d3f57cSMariusz Zaborski close(fd_out);
136*62d3f57cSMariusz Zaborski }
137*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,ReadWrite)138*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, ReadWrite) {
139*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
140*62d3f57cSMariusz Zaborski
141*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_READ);
142*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_WRITE);
143*62d3f57cSMariusz Zaborski
144*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
145*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
146*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
147*62d3f57cSMariusz Zaborski
148*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
149*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
150*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
151*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
152*62d3f57cSMariusz Zaborski off_in = 20;
153*62d3f57cSMariusz Zaborski off_out = 20;
154*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
155*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
156*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
157*62d3f57cSMariusz Zaborski close(fd_in);
158*62d3f57cSMariusz Zaborski close(fd_out);
159*62d3f57cSMariusz Zaborski }
160*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,ReadSeekWrite)161*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, ReadSeekWrite) {
162*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
163*62d3f57cSMariusz Zaborski
164*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_READ, CAP_SEEK);
165*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_WRITE);
166*62d3f57cSMariusz Zaborski
167*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
168*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
169*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
170*62d3f57cSMariusz Zaborski
171*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
172*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
173*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
174*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
175*62d3f57cSMariusz Zaborski off_in = 20;
176*62d3f57cSMariusz Zaborski off_out = 20;
177*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
178*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
179*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
180*62d3f57cSMariusz Zaborski close(fd_in);
181*62d3f57cSMariusz Zaborski close(fd_out);
182*62d3f57cSMariusz Zaborski }
183*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,ReadWriteSeek)184*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, ReadWriteSeek) {
185*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
186*62d3f57cSMariusz Zaborski
187*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_READ);
188*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_WRITE, CAP_SEEK);
189*62d3f57cSMariusz Zaborski
190*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
191*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
192*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
193*62d3f57cSMariusz Zaborski
194*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
195*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
196*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
197*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
198*62d3f57cSMariusz Zaborski off_in = 20;
199*62d3f57cSMariusz Zaborski off_out = 20;
200*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
201*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
202*62d3f57cSMariusz Zaborski EXPECT_NOTCAPABLE(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
203*62d3f57cSMariusz Zaborski close(fd_in);
204*62d3f57cSMariusz Zaborski close(fd_out);
205*62d3f57cSMariusz Zaborski }
206*62d3f57cSMariusz Zaborski
TEST_F(CopyFileRangeTest,ReadSeekWriteSeek)207*62d3f57cSMariusz Zaborski TEST_F(CopyFileRangeTest, ReadSeekWriteSeek) {
208*62d3f57cSMariusz Zaborski cap_rights_t rights_in, rights_out;
209*62d3f57cSMariusz Zaborski
210*62d3f57cSMariusz Zaborski cap_rights_init(&rights_in, CAP_READ, CAP_SEEK);
211*62d3f57cSMariusz Zaborski cap_rights_init(&rights_out, CAP_WRITE, CAP_SEEK);
212*62d3f57cSMariusz Zaborski
213*62d3f57cSMariusz Zaborski int fd_in = openInFile(&rights_in);
214*62d3f57cSMariusz Zaborski int fd_out = openOutFile(&rights_out);
215*62d3f57cSMariusz Zaborski off_t off_in = 0, off_out = 0;
216*62d3f57cSMariusz Zaborski
217*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, NULL, 8, 0));
218*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
219*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
220*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
221*62d3f57cSMariusz Zaborski off_in = 20;
222*62d3f57cSMariusz Zaborski off_out = 20;
223*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, NULL, fd_out, &off_out, 8, 0));
224*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, &off_in, fd_out, NULL, 8, 0));
225*62d3f57cSMariusz Zaborski EXPECT_OK(copy_file_range(fd_in, &off_in, fd_out, &off_out, 8, 0));
226*62d3f57cSMariusz Zaborski close(fd_in);
227*62d3f57cSMariusz Zaborski close(fd_out);
228*62d3f57cSMariusz Zaborski }
229