github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/sendfile.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <fcntl.h> 16 #include <linux/unistd.h> 17 #include <sys/eventfd.h> 18 #include <sys/sendfile.h> 19 #include <unistd.h> 20 21 #include "gmock/gmock.h" 22 #include "gtest/gtest.h" 23 #include "absl/strings/string_view.h" 24 #include "absl/time/clock.h" 25 #include "absl/time/time.h" 26 #include "test/util/eventfd_util.h" 27 #include "test/util/file_descriptor.h" 28 #include "test/util/signal_util.h" 29 #include "test/util/temp_path.h" 30 #include "test/util/test_util.h" 31 #include "test/util/thread_util.h" 32 #include "test/util/timer_util.h" 33 34 namespace gvisor { 35 namespace testing { 36 37 namespace { 38 39 TEST(SendFileTest, SendZeroBytes) { 40 // Create temp files. 41 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 42 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 43 44 // Open the input file as read only. 45 const FileDescriptor inf = 46 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 47 48 // Open the output file as write only. 49 const FileDescriptor outf = 50 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 51 52 // Send data and verify that sendfile returns the correct value. 53 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 0), 54 SyscallSucceedsWithValue(0)); 55 } 56 57 TEST(SendFileTest, InvalidOffset) { 58 // Create temp files. 59 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 60 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 61 62 // Open the input file as read only. 63 const FileDescriptor inf = 64 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 65 66 // Open the output file as write only. 67 const FileDescriptor outf = 68 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 69 70 // Send data and verify that sendfile returns the correct value. 71 off_t offset = -1; 72 EXPECT_THAT(sendfile(outf.get(), inf.get(), &offset, 0), 73 SyscallFailsWithErrno(EINVAL)); 74 } 75 76 int memfd_create(const std::string& name, unsigned int flags) { 77 return syscall(__NR_memfd_create, name.c_str(), flags); 78 } 79 80 TEST(SendFileTest, Overflow) { 81 // Create input file. 82 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 83 const FileDescriptor inf = 84 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 85 86 // Open the output file. 87 int fd; 88 EXPECT_THAT(fd = memfd_create("overflow", 0), SyscallSucceeds()); 89 const FileDescriptor outf(fd); 90 91 // out_offset + kSize overflows INT64_MAX. 92 loff_t out_offset = 0x7ffffffffffffffeull; 93 constexpr int kSize = 3; 94 EXPECT_THAT(sendfile(outf.get(), inf.get(), &out_offset, kSize), 95 SyscallFailsWithErrno(EINVAL)); 96 } 97 98 TEST(SendFileTest, SendTrivially) { 99 // Create temp files. 100 constexpr char kData[] = "To be, or not to be, that is the question:"; 101 constexpr int kDataSize = sizeof(kData) - 1; 102 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 103 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 104 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 105 106 // Open the input file as read only. 107 const FileDescriptor inf = 108 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 109 110 // Open the output file as write only. 111 FileDescriptor outf; 112 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 113 114 // Send data and verify that sendfile returns the correct value. 115 int bytes_sent; 116 EXPECT_THAT(bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize), 117 SyscallSucceedsWithValue(kDataSize)); 118 119 // Close outf to avoid leak. 120 outf.reset(); 121 122 // Open the output file as read only. 123 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 124 125 // Verify that the output file has the correct data. 126 char actual[kDataSize]; 127 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 128 SyscallSucceedsWithValue(kDataSize)); 129 EXPECT_EQ(kData, absl::string_view(actual, bytes_sent)); 130 } 131 132 TEST(SendFileTest, SendTriviallyWithBothFilesReadWrite) { 133 // Create temp files. 134 constexpr char kData[] = "Whether 'tis nobler in the mind to suffer"; 135 constexpr int kDataSize = sizeof(kData) - 1; 136 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 137 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 138 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 139 140 // Open the input file as readwrite. 141 const FileDescriptor inf = 142 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR)); 143 144 // Open the output file as readwrite. 145 FileDescriptor outf; 146 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDWR)); 147 148 // Send data and verify that sendfile returns the correct value. 149 int bytes_sent; 150 EXPECT_THAT(bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize), 151 SyscallSucceedsWithValue(kDataSize)); 152 153 // Close outf to avoid leak. 154 outf.reset(); 155 156 // Open the output file as read only. 157 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 158 159 // Verify that the output file has the correct data. 160 char actual[kDataSize]; 161 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 162 SyscallSucceedsWithValue(kDataSize)); 163 EXPECT_EQ(kData, absl::string_view(actual, bytes_sent)); 164 } 165 166 TEST(SendFileTest, SendAndUpdateFileOffset) { 167 // Create temp files. 168 // Test input string length must be > 2 AND even. 169 constexpr char kData[] = "The slings and arrows of outrageous fortune,"; 170 constexpr int kDataSize = sizeof(kData) - 1; 171 constexpr int kHalfDataSize = kDataSize / 2; 172 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 173 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 174 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 175 176 // Open the input file as read only. 177 const FileDescriptor inf = 178 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 179 180 // Open the output file as write only. 181 FileDescriptor outf; 182 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 183 184 // Send data and verify that sendfile returns the correct value. 185 int bytes_sent; 186 EXPECT_THAT( 187 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize), 188 SyscallSucceedsWithValue(kHalfDataSize)); 189 190 // Close outf to avoid leak. 191 outf.reset(); 192 193 // Open the output file as read only. 194 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 195 196 // Verify that the output file has the correct data. 197 char actual[kHalfDataSize]; 198 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 199 SyscallSucceedsWithValue(kHalfDataSize)); 200 EXPECT_EQ(absl::string_view(kData, kHalfDataSize), 201 absl::string_view(actual, bytes_sent)); 202 203 // Verify that the input file offset has been updated. 204 ASSERT_THAT(read(inf.get(), &actual, kDataSize - bytes_sent), 205 SyscallSucceedsWithValue(kHalfDataSize)); 206 EXPECT_EQ( 207 absl::string_view(kData + kDataSize - bytes_sent, kDataSize - bytes_sent), 208 absl::string_view(actual, kHalfDataSize)); 209 } 210 211 TEST(SendFileTest, SendToDevZeroAndUpdateFileOffset) { 212 // Create temp files. 213 // Test input string length must be > 2 AND even. 214 constexpr char kData[] = "The slings and arrows of outrageous fortune,"; 215 constexpr int kDataSize = sizeof(kData) - 1; 216 constexpr int kHalfDataSize = kDataSize / 2; 217 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 218 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 219 220 // Open the input file as read only. 221 const FileDescriptor inf = 222 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 223 224 // Open /dev/zero as write only. 225 const FileDescriptor outf = 226 ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/zero", O_WRONLY)); 227 228 // Send data and verify that sendfile returns the correct value. 229 int bytes_sent; 230 EXPECT_THAT( 231 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize), 232 SyscallSucceedsWithValue(kHalfDataSize)); 233 234 char actual[kHalfDataSize]; 235 // Verify that the input file offset has been updated. 236 ASSERT_THAT(read(inf.get(), &actual, kDataSize - bytes_sent), 237 SyscallSucceedsWithValue(kHalfDataSize)); 238 EXPECT_EQ( 239 absl::string_view(kData + kDataSize - bytes_sent, kDataSize - bytes_sent), 240 absl::string_view(actual, kHalfDataSize)); 241 } 242 243 TEST(SendFileTest, SendAndUpdateFileOffsetFromNonzeroStartingPoint) { 244 // Create temp files. 245 // Test input string length must be > 2 AND divisible by 4. 246 constexpr char kData[] = "The slings and arrows of outrageous fortune,"; 247 constexpr int kDataSize = sizeof(kData) - 1; 248 constexpr int kHalfDataSize = kDataSize / 2; 249 constexpr int kQuarterDataSize = kHalfDataSize / 2; 250 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 251 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 252 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 253 254 // Open the input file as read only. 255 const FileDescriptor inf = 256 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 257 258 // Open the output file as write only. 259 FileDescriptor outf; 260 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 261 262 // Read a quarter of the data from the infile which should update the file 263 // offset, we don't actually care about the data so it goes into the garbage. 264 char garbage[kQuarterDataSize]; 265 ASSERT_THAT(read(inf.get(), &garbage, kQuarterDataSize), 266 SyscallSucceedsWithValue(kQuarterDataSize)); 267 268 // Send data and verify that sendfile returns the correct value. 269 int bytes_sent; 270 EXPECT_THAT( 271 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize), 272 SyscallSucceedsWithValue(kHalfDataSize)); 273 274 // Close out_fd to avoid leak. 275 outf.reset(); 276 277 // Open the output file as read only. 278 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 279 280 // Verify that the output file has the correct data. 281 char actual[kHalfDataSize]; 282 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 283 SyscallSucceedsWithValue(kHalfDataSize)); 284 EXPECT_EQ(absl::string_view(kData + kQuarterDataSize, kHalfDataSize), 285 absl::string_view(actual, bytes_sent)); 286 287 // Verify that the input file offset has been updated. 288 ASSERT_THAT(read(inf.get(), &actual, kQuarterDataSize), 289 SyscallSucceedsWithValue(kQuarterDataSize)); 290 291 EXPECT_EQ( 292 absl::string_view(kData + kDataSize - kQuarterDataSize, kQuarterDataSize), 293 absl::string_view(actual, kQuarterDataSize)); 294 } 295 296 TEST(SendFileTest, SendAndUpdateGivenOffset) { 297 // Create temp files. 298 // Test input string length must be >= 4 AND divisible by 4. 299 constexpr char kData[] = "Or to take Arms against a Sea of troubles,"; 300 constexpr int kDataSize = sizeof(kData) + 1; 301 constexpr int kHalfDataSize = kDataSize / 2; 302 constexpr int kQuarterDataSize = kHalfDataSize / 2; 303 constexpr int kThreeFourthsDataSize = 3 * kDataSize / 4; 304 305 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 306 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 307 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 308 309 // Open the input file as read only. 310 const FileDescriptor inf = 311 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 312 313 // Open the output file as write only. 314 FileDescriptor outf; 315 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 316 317 // Create offset for sending. 318 off_t offset = kQuarterDataSize; 319 320 // Send data and verify that sendfile returns the correct value. 321 int bytes_sent; 322 EXPECT_THAT( 323 bytes_sent = sendfile(outf.get(), inf.get(), &offset, kHalfDataSize), 324 SyscallSucceedsWithValue(kHalfDataSize)); 325 326 // Close out_fd to avoid leak. 327 outf.reset(); 328 329 // Open the output file as read only. 330 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 331 332 // Verify that the output file has the correct data. 333 char actual[kHalfDataSize]; 334 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 335 SyscallSucceedsWithValue(kHalfDataSize)); 336 EXPECT_EQ(absl::string_view(kData + kQuarterDataSize, kHalfDataSize), 337 absl::string_view(actual, bytes_sent)); 338 339 // Verify that the input file offset has NOT been updated. 340 ASSERT_THAT(read(inf.get(), &actual, kHalfDataSize), 341 SyscallSucceedsWithValue(kHalfDataSize)); 342 EXPECT_EQ(absl::string_view(kData, kHalfDataSize), 343 absl::string_view(actual, kHalfDataSize)); 344 345 // Verify that the offset pointer has been updated. 346 EXPECT_EQ(offset, kThreeFourthsDataSize); 347 } 348 349 TEST(SendFileTest, DoNotSendfileIfOutfileIsAppendOnly) { 350 // Create temp files. 351 constexpr char kData[] = "And by opposing end them: to die, to sleep"; 352 constexpr int kDataSize = sizeof(kData) - 1; 353 354 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 355 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 356 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 357 358 // Open the input file as read only. 359 const FileDescriptor inf = 360 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 361 362 // Open the output file as append only. 363 const FileDescriptor outf = 364 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY | O_APPEND)); 365 366 // Send data and verify that sendfile returns the correct errno. 367 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize), 368 SyscallFailsWithErrno(EINVAL)); 369 } 370 371 TEST(SendFileTest, AppendCheckOrdering) { 372 constexpr char kData[] = "And by opposing end them: to die, to sleep"; 373 constexpr int kDataSize = sizeof(kData) - 1; 374 const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 375 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 376 377 const FileDescriptor read = 378 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY)); 379 const FileDescriptor write = 380 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY)); 381 const FileDescriptor append = 382 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_APPEND)); 383 384 // Check that read/write file mode is verified before append. 385 EXPECT_THAT(sendfile(append.get(), read.get(), nullptr, kDataSize), 386 SyscallFailsWithErrno(EBADF)); 387 EXPECT_THAT(sendfile(write.get(), write.get(), nullptr, kDataSize), 388 SyscallFailsWithErrno(EBADF)); 389 } 390 391 TEST(SendFileTest, DoNotSendfileIfOutfileIsNotWritable) { 392 // Create temp files. 393 constexpr char kData[] = "No more; and by a sleep, to say we end"; 394 constexpr int kDataSize = sizeof(kData) - 1; 395 396 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 397 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 398 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 399 400 // Open the input file as read only. 401 const FileDescriptor inf = 402 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 403 404 // Open the output file as read only. 405 const FileDescriptor outf = 406 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 407 408 // Send data and verify that sendfile returns the correct errno. 409 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize), 410 SyscallFailsWithErrno(EBADF)); 411 } 412 413 TEST(SendFileTest, DoNotSendfileIfInfileIsNotReadable) { 414 // Create temp files. 415 constexpr char kData[] = "the heart-ache, and the thousand natural shocks"; 416 constexpr int kDataSize = sizeof(kData) - 1; 417 418 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 419 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 420 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 421 422 // Open the input file as write only. 423 const FileDescriptor inf = 424 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_WRONLY)); 425 426 // Open the output file as write only. 427 const FileDescriptor outf = 428 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 429 430 // Send data and verify that sendfile returns the correct errno. 431 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize), 432 SyscallFailsWithErrno(EBADF)); 433 } 434 435 TEST(SendFileTest, DoNotSendANegativeNumberOfBytes) { 436 // Create temp files. 437 constexpr char kData[] = "that Flesh is heir to? 'Tis a consummation"; 438 439 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 440 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 441 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 442 443 // Open the input file as read only. 444 const FileDescriptor inf = 445 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 446 447 // Open the output file as write only. 448 const FileDescriptor outf = 449 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 450 451 // Send data and verify that sendfile returns the correct errno. 452 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, -1), 453 SyscallFailsWithErrno(EINVAL)); 454 } 455 456 TEST(SendFileTest, SendTheCorrectNumberOfBytesEvenIfWeTryToSendTooManyBytes) { 457 // Create temp files. 458 constexpr char kData[] = "devoutly to be wished. To die, to sleep,"; 459 constexpr int kDataSize = sizeof(kData) - 1; 460 461 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 462 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 463 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 464 465 // Open the input file as read only. 466 const FileDescriptor inf = 467 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 468 469 // Open the output file as write only. 470 FileDescriptor outf; 471 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 472 473 // Send data and verify that sendfile returns the correct value. 474 int bytes_sent; 475 EXPECT_THAT( 476 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize + 100), 477 SyscallSucceedsWithValue(kDataSize)); 478 479 // Close outf to avoid leak. 480 outf.reset(); 481 482 // Open the output file as read only. 483 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 484 485 // Verify that the output file has the correct data. 486 char actual[kDataSize]; 487 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 488 SyscallSucceedsWithValue(kDataSize)); 489 EXPECT_EQ(kData, absl::string_view(actual, bytes_sent)); 490 } 491 492 TEST(SendFileTest, SendToNotARegularFile) { 493 // Make temp input directory and open as read only. 494 const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 495 const FileDescriptor inf = 496 ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY)); 497 498 // Make temp output file and open as write only. 499 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 500 const FileDescriptor outf = 501 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 502 503 // Receive an error since a directory is not a regular file. 504 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 0), 505 SyscallFailsWithErrno(EINVAL)); 506 } 507 508 TEST(SendFileTest, SendPipeWouldBlock) { 509 // Create temp file. 510 constexpr char kData[] = 511 "The fool doth think he is wise, but the wise man knows himself to be a " 512 "fool."; 513 constexpr int kDataSize = sizeof(kData) - 1; 514 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 515 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 516 517 // Open the input file as read only. 518 const FileDescriptor inf = 519 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 520 521 // Setup the output named pipe. 522 int fds[2]; 523 ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); 524 const FileDescriptor rfd(fds[0]); 525 const FileDescriptor wfd(fds[1]); 526 527 // Fill up the pipe's buffer. 528 int pipe_size = -1; 529 ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); 530 std::vector<char> buf(2 * pipe_size); 531 ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()), 532 SyscallSucceedsWithValue(pipe_size)); 533 534 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize), 535 SyscallFailsWithErrno(EWOULDBLOCK)); 536 } 537 538 TEST(SendFileTest, SendPipeEOF) { 539 // Create and open an empty input file. 540 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 541 const FileDescriptor inf = 542 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 543 544 // Setup the output named pipe. 545 int fds[2]; 546 ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); 547 const FileDescriptor rfd(fds[0]); 548 const FileDescriptor wfd(fds[1]); 549 550 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, 123), 551 SyscallSucceedsWithValue(0)); 552 } 553 554 TEST(SendFileTest, SendToFullPipeReturnsEAGAIN) { 555 // Create and open an empty input file. 556 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 557 const FileDescriptor in_fd = 558 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR)); 559 560 // Set up the output pipe. 561 int fds[2]; 562 ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); 563 const FileDescriptor rfd(fds[0]); 564 const FileDescriptor wfd(fds[1]); 565 566 int pipe_size = -1; 567 ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); 568 int data_size = pipe_size * 8; 569 ASSERT_THAT(ftruncate(in_fd.get(), data_size), SyscallSucceeds()); 570 571 ASSERT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size), 572 SyscallSucceeds()); 573 EXPECT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size), 574 SyscallFailsWithErrno(EAGAIN)); 575 } 576 577 TEST(SendFileTest, SendPipeBlocks) { 578 // Create temp file. 579 constexpr char kData[] = 580 "The fault, dear Brutus, is not in our stars, but in ourselves."; 581 constexpr int kDataSize = sizeof(kData) - 1; 582 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 583 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 584 585 // Open the input file as read only. 586 const FileDescriptor inf = 587 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 588 589 // Setup the output named pipe. 590 int fds[2]; 591 ASSERT_THAT(pipe(fds), SyscallSucceeds()); 592 const FileDescriptor rfd(fds[0]); 593 const FileDescriptor wfd(fds[1]); 594 595 // Fill up the pipe's buffer. 596 int pipe_size = -1; 597 ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); 598 std::vector<char> buf(pipe_size); 599 ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()), 600 SyscallSucceedsWithValue(pipe_size)); 601 602 ScopedThread t([&]() { 603 absl::SleepFor(absl::Milliseconds(100)); 604 ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()), 605 SyscallSucceedsWithValue(pipe_size)); 606 }); 607 608 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize), 609 SyscallSucceedsWithValue(kDataSize)); 610 } 611 612 TEST(SendFileTest, SendToSpecialFile) { 613 // Create temp file. 614 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 615 GetAbsoluteTestTmpdir(), "", TempPath::kDefaultFileMode)); 616 617 const FileDescriptor inf = 618 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR)); 619 constexpr int kSize = 0x7ff; 620 ASSERT_THAT(ftruncate(inf.get(), kSize), SyscallSucceeds()); 621 622 auto eventfd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD()); 623 624 // eventfd can accept a number of bytes which is a multiple of 8. 625 EXPECT_THAT(sendfile(eventfd.get(), inf.get(), nullptr, 0xfffff), 626 SyscallSucceedsWithValue(kSize & (~7))); 627 } 628 629 TEST(SendFileTest, SendFileToPipe) { 630 // Create temp file. 631 constexpr char kData[] = "<insert-quote-here>"; 632 constexpr int kDataSize = sizeof(kData) - 1; 633 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 634 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 635 const FileDescriptor inf = 636 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 637 638 // Create a pipe for sending to a pipe. 639 int fds[2]; 640 ASSERT_THAT(pipe(fds), SyscallSucceeds()); 641 const FileDescriptor rfd(fds[0]); 642 const FileDescriptor wfd(fds[1]); 643 644 // Expect to read up to the given size. 645 std::vector<char> buf(kDataSize); 646 ScopedThread t([&]() { 647 absl::SleepFor(absl::Milliseconds(100)); 648 ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()), 649 SyscallSucceedsWithValue(kDataSize)); 650 }); 651 652 // Send with twice the size of the file, which should hit EOF. 653 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize * 2), 654 SyscallSucceedsWithValue(kDataSize)); 655 } 656 657 TEST(SendFileTest, SendFileToSelf) { 658 int rawfd; 659 ASSERT_THAT(rawfd = memfd_create("memfd", 0), SyscallSucceeds()); 660 const FileDescriptor fd(rawfd); 661 662 char c = 0x01; 663 ASSERT_THAT(WriteFd(fd.get(), &c, 1), SyscallSucceedsWithValue(1)); 664 665 // Arbitrarily chosen to make sendfile() take long enough that the sentry 666 // watchdog usually fires unless it's reset by sendfile() between iterations 667 // of the buffered copy. See b/172076632. 668 constexpr size_t kSendfileSize = 0xa00000; 669 670 off_t offset = 0; 671 ASSERT_THAT(sendfile(fd.get(), fd.get(), &offset, kSendfileSize), 672 SyscallSucceedsWithValue(kSendfileSize)); 673 } 674 675 static volatile int signaled = 0; 676 void SigUsr1Handler(int sig, siginfo_t* info, void* context) { signaled = 1; } 677 678 TEST(SendFileTest, ToEventFDDoesNotSpin) { 679 FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0)); 680 681 // Write the maximum value of an eventfd to a file. 682 const uint64_t kMaxEventfdValue = 0xfffffffffffffffe; 683 const auto tempfile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 684 const auto tempfd = ASSERT_NO_ERRNO_AND_VALUE(Open(tempfile.path(), O_RDWR)); 685 ASSERT_THAT( 686 pwrite(tempfd.get(), &kMaxEventfdValue, sizeof(kMaxEventfdValue), 0), 687 SyscallSucceedsWithValue(sizeof(kMaxEventfdValue))); 688 689 // Set the eventfd's value to 1. 690 const uint64_t kOne = 1; 691 ASSERT_THAT(write(efd.get(), &kOne, sizeof(kOne)), 692 SyscallSucceedsWithValue(sizeof(kOne))); 693 694 // Set up signal handler. 695 struct sigaction sa = {}; 696 sa.sa_sigaction = SigUsr1Handler; 697 sa.sa_flags = SA_SIGINFO; 698 const auto cleanup_sigact = 699 ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGUSR1, sa)); 700 701 // Send SIGUSR1 to this thread in 1 second. 702 struct sigevent sev = {}; 703 sev.sigev_notify = SIGEV_THREAD_ID; 704 sev.sigev_signo = SIGUSR1; 705 sev.sigev_notify_thread_id = gettid(); 706 auto timer = ASSERT_NO_ERRNO_AND_VALUE(TimerCreate(CLOCK_MONOTONIC, sev)); 707 struct itimerspec its = {}; 708 its.it_value = absl::ToTimespec(absl::Seconds(1)); 709 DisableSave ds; // Asserting an EINTR. 710 ASSERT_NO_ERRNO(timer.Set(0, its)); 711 712 // Sendfile from tempfd to the eventfd. Since the eventfd is not already at 713 // its maximum value, the eventfd is "ready for writing"; however, since the 714 // eventfd's existing value plus the new value would exceed the maximum, the 715 // write should internally fail with EWOULDBLOCK. In this case, sendfile() 716 // should block instead of spinning, and eventually be interrupted by our 717 // timer. See b/172075629. 718 EXPECT_THAT( 719 sendfile(efd.get(), tempfd.get(), nullptr, sizeof(kMaxEventfdValue)), 720 SyscallFailsWithErrno(EINTR)); 721 722 // Signal should have been handled. 723 EXPECT_EQ(signaled, 1); 724 } 725 726 } // namespace 727 728 } // namespace testing 729 } // namespace gvisor