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