github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/read.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 <sys/mman.h>
    17  #include <unistd.h>
    18  
    19  #include <vector>
    20  
    21  #include "gtest/gtest.h"
    22  #include "absl/base/macros.h"
    23  #include "test/util/cleanup.h"
    24  #include "test/util/file_descriptor.h"
    25  #include "test/util/temp_path.h"
    26  #include "test/util/test_util.h"
    27  
    28  namespace gvisor {
    29  namespace testing {
    30  
    31  namespace {
    32  
    33  class ReadTest : public ::testing::Test {
    34    void SetUp() override {
    35      name_ = NewTempAbsPath();
    36      int fd;
    37      ASSERT_THAT(fd = open(name_.c_str(), O_CREAT, 0644), SyscallSucceeds());
    38      ASSERT_THAT(close(fd), SyscallSucceeds());
    39    }
    40  
    41    void TearDown() override { unlink(name_.c_str()); }
    42  
    43   public:
    44    std::string name_;
    45  };
    46  
    47  TEST_F(ReadTest, ZeroBuffer) {
    48    int fd;
    49    ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());
    50  
    51    char msg[] = "hello world";
    52    EXPECT_THAT(PwriteFd(fd, msg, strlen(msg), 0),
    53                SyscallSucceedsWithValue(strlen(msg)));
    54  
    55    char buf[10];
    56    EXPECT_THAT(ReadFd(fd, buf, 0), SyscallSucceedsWithValue(0));
    57    EXPECT_THAT(close(fd), SyscallSucceeds());
    58  }
    59  
    60  TEST_F(ReadTest, EmptyFileReturnsZeroAtEOF) {
    61    int fd;
    62    ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());
    63  
    64    char eof_buf[10];
    65    EXPECT_THAT(ReadFd(fd, eof_buf, 10), SyscallSucceedsWithValue(0));
    66    EXPECT_THAT(close(fd), SyscallSucceeds());
    67  }
    68  
    69  TEST_F(ReadTest, EofAfterRead) {
    70    int fd;
    71    ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());
    72  
    73    // Write some bytes to be read.
    74    constexpr char kMessage[] = "hello world";
    75    EXPECT_THAT(PwriteFd(fd, kMessage, sizeof(kMessage), 0),
    76                SyscallSucceedsWithValue(sizeof(kMessage)));
    77  
    78    // Read all of the bytes at once.
    79    char buf[sizeof(kMessage)];
    80    EXPECT_THAT(ReadFd(fd, buf, sizeof(kMessage)),
    81                SyscallSucceedsWithValue(sizeof(kMessage)));
    82  
    83    // Read again with a non-zero buffer and expect EOF.
    84    char eof_buf[10];
    85    EXPECT_THAT(ReadFd(fd, eof_buf, 10), SyscallSucceedsWithValue(0));
    86    EXPECT_THAT(close(fd), SyscallSucceeds());
    87  }
    88  
    89  TEST_F(ReadTest, DevNullReturnsEof) {
    90    int fd;
    91    ASSERT_THAT(fd = open("/dev/null", O_RDONLY), SyscallSucceeds());
    92    std::vector<char> buf(1);
    93    EXPECT_THAT(ReadFd(fd, buf.data(), 1), SyscallSucceedsWithValue(0));
    94    EXPECT_THAT(close(fd), SyscallSucceeds());
    95  }
    96  
    97  const int kReadSize = 128 * 1024;
    98  
    99  // Do not allow random save as it could lead to partial reads.
   100  TEST_F(ReadTest, CanReadFullyFromDevZero) {
   101    int fd;
   102    ASSERT_THAT(fd = open("/dev/zero", O_RDONLY), SyscallSucceeds());
   103  
   104    std::vector<char> buf(kReadSize, 1);
   105    EXPECT_THAT(ReadFd(fd, buf.data(), kReadSize),
   106                SyscallSucceedsWithValue(kReadSize));
   107    EXPECT_THAT(close(fd), SyscallSucceeds());
   108    EXPECT_EQ(std::vector<char>(kReadSize, 0), buf);
   109  }
   110  
   111  TEST_F(ReadTest, ReadDirectoryFails) {
   112    const FileDescriptor file =
   113        ASSERT_NO_ERRNO_AND_VALUE(Open(GetAbsoluteTestTmpdir(), O_RDONLY));
   114    std::vector<char> buf(1);
   115    EXPECT_THAT(ReadFd(file.get(), buf.data(), 1), SyscallFailsWithErrno(EISDIR));
   116  }
   117  
   118  TEST_F(ReadTest, ReadWithOpath) {
   119    SKIP_IF(IsRunningWithVFS1());
   120    const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   121    const FileDescriptor fd =
   122        ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_PATH));
   123    std::vector<char> buf(1);
   124    EXPECT_THAT(ReadFd(fd.get(), buf.data(), 1), SyscallFailsWithErrno(EBADF));
   125  }
   126  
   127  // Test that partial writes that hit SIGSEGV are correctly handled and return
   128  // partial write.
   129  TEST_F(ReadTest, PartialReadSIGSEGV) {
   130    // Allocate 2 pages and remove permission from the second.
   131    const size_t size = 2 * kPageSize;
   132    void* addr =
   133        mmap(0, size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
   134    ASSERT_NE(addr, MAP_FAILED);
   135    auto cleanup = Cleanup(
   136        [addr, size] { EXPECT_THAT(munmap(addr, size), SyscallSucceeds()); });
   137  
   138    FileDescriptor fd =
   139        ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR, 0666));
   140    for (size_t i = 0; i < 2; i++) {
   141      EXPECT_THAT(pwrite(fd.get(), addr, size, 0),
   142                  SyscallSucceedsWithValue(size));
   143    }
   144  
   145    void* badAddr = reinterpret_cast<char*>(addr) + kPageSize;
   146    ASSERT_THAT(mprotect(badAddr, kPageSize, PROT_NONE), SyscallSucceeds());
   147  
   148    // Attempt to read to both pages. Create a non-contiguous iovec pair to
   149    // ensure operation is done in 2 steps.
   150    struct iovec iov[] = {
   151        {
   152            .iov_base = addr,
   153            .iov_len = kPageSize,
   154        },
   155        {
   156            .iov_base = addr,
   157            .iov_len = size,
   158        },
   159    };
   160    EXPECT_THAT(lseek(fd.get(), 0, SEEK_SET), SyscallSucceeds());
   161    EXPECT_THAT(readv(fd.get(), iov, ABSL_ARRAYSIZE(iov)),
   162                SyscallSucceedsWithValue(size));
   163  }
   164  
   165  }  // namespace
   166  
   167  }  // namespace testing
   168  }  // namespace gvisor