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: 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 } 34 ~CopyFileRangeTest() { 35 close(wd_); 36 unlink(TmpFile(TOPDIR "/" INFILE)); 37 unlink(TmpFile(TOPDIR "/" OUTFILE)); 38 rmdir(TmpFile(TOPDIR)); 39 } 40 41 private: 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 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 } 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 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 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 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 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 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 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 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