github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/fallocate.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 <errno.h>
    16  #include <fcntl.h>
    17  #include <signal.h>
    18  #include <sys/eventfd.h>
    19  #include <sys/resource.h>
    20  #include <sys/signalfd.h>
    21  #include <sys/socket.h>
    22  #include <sys/stat.h>
    23  #include <sys/timerfd.h>
    24  #include <syscall.h>
    25  #include <time.h>
    26  #include <unistd.h>
    27  
    28  #include <ctime>
    29  
    30  #include "gtest/gtest.h"
    31  #include "absl/strings/str_cat.h"
    32  #include "absl/time/time.h"
    33  #include "test/syscalls/linux/file_base.h"
    34  #include "test/syscalls/linux/socket_test_util.h"
    35  #include "test/util/cleanup.h"
    36  #include "test/util/eventfd_util.h"
    37  #include "test/util/file_descriptor.h"
    38  #include "test/util/posix_error.h"
    39  #include "test/util/temp_path.h"
    40  #include "test/util/test_util.h"
    41  
    42  namespace gvisor {
    43  namespace testing {
    44  namespace {
    45  
    46  int fallocate(int fd, int mode, off_t offset, off_t len) {
    47    return RetryEINTR(syscall)(__NR_fallocate, fd, mode, offset, len);
    48  }
    49  
    50  class AllocateTest : public FileTest {
    51    void SetUp() override { FileTest::SetUp(); }
    52  };
    53  
    54  TEST_F(AllocateTest, Fallocate) {
    55    // Check that it starts at size zero.
    56    struct stat buf;
    57    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    58    EXPECT_EQ(buf.st_size, 0);
    59  
    60    // Grow to ten bytes.
    61    ASSERT_THAT(fallocate(test_file_fd_.get(), 0, 0, 10), SyscallSucceeds());
    62    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    63    EXPECT_EQ(buf.st_size, 10);
    64  
    65    // Allocate to a smaller size should be noop.
    66    ASSERT_THAT(fallocate(test_file_fd_.get(), 0, 0, 5), SyscallSucceeds());
    67    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    68    EXPECT_EQ(buf.st_size, 10);
    69  
    70    // Grow again.
    71    ASSERT_THAT(fallocate(test_file_fd_.get(), 0, 0, 20), SyscallSucceeds());
    72    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    73    EXPECT_EQ(buf.st_size, 20);
    74  
    75    // Grow with offset.
    76    ASSERT_THAT(fallocate(test_file_fd_.get(), 0, 10, 20), SyscallSucceeds());
    77    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    78    EXPECT_EQ(buf.st_size, 30);
    79  
    80    // Grow with offset beyond EOF.
    81    ASSERT_THAT(fallocate(test_file_fd_.get(), 0, 39, 1), SyscallSucceeds());
    82    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    83    EXPECT_EQ(buf.st_size, 40);
    84  
    85    // Given length 0 should fail with EINVAL.
    86    ASSERT_THAT(fallocate(test_file_fd_.get(), 0, 50, 0),
    87                SyscallFailsWithErrno(EINVAL));
    88    ASSERT_THAT(fstat(test_file_fd_.get(), &buf), SyscallSucceeds());
    89    EXPECT_EQ(buf.st_size, 40);
    90  }
    91  
    92  TEST_F(AllocateTest, FallocateInvalid) {
    93    // Invalid FD
    94    EXPECT_THAT(fallocate(-1, 0, 0, 10), SyscallFailsWithErrno(EBADF));
    95  
    96    // Negative offset and size.
    97    EXPECT_THAT(fallocate(test_file_fd_.get(), 0, -1, 10),
    98                SyscallFailsWithErrno(EINVAL));
    99    EXPECT_THAT(fallocate(test_file_fd_.get(), 0, 0, -1),
   100                SyscallFailsWithErrno(EINVAL));
   101    EXPECT_THAT(fallocate(test_file_fd_.get(), 0, -1, -1),
   102                SyscallFailsWithErrno(EINVAL));
   103  }
   104  
   105  TEST_F(AllocateTest, FallocateReadonly) {
   106    auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   107    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
   108    EXPECT_THAT(fallocate(fd.get(), 0, 0, 10), SyscallFailsWithErrno(EBADF));
   109  }
   110  
   111  TEST_F(AllocateTest, FallocateWithOpath) {
   112    SKIP_IF(IsRunningWithVFS1());
   113    auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   114    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_PATH));
   115    EXPECT_THAT(fallocate(fd.get(), 0, 0, 10), SyscallFailsWithErrno(EBADF));
   116  }
   117  
   118  TEST_F(AllocateTest, FallocatePipe) {
   119    int pipes[2];
   120    EXPECT_THAT(pipe(pipes), SyscallSucceeds());
   121    auto cleanup = Cleanup([&pipes] {
   122      EXPECT_THAT(close(pipes[0]), SyscallSucceeds());
   123      EXPECT_THAT(close(pipes[1]), SyscallSucceeds());
   124    });
   125  
   126    EXPECT_THAT(fallocate(pipes[1], 0, 0, 10), SyscallFailsWithErrno(ESPIPE));
   127  }
   128  
   129  TEST_F(AllocateTest, FallocateChar) {
   130    const FileDescriptor fd =
   131        ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/null", O_RDWR));
   132    EXPECT_THAT(fallocate(fd.get(), 0, 0, 10), SyscallFailsWithErrno(ENODEV));
   133  }
   134  
   135  TEST_F(AllocateTest, FallocateRlimit) {
   136    // Get the current rlimit and restore after test run.
   137    struct rlimit initial_lim;
   138    ASSERT_THAT(getrlimit(RLIMIT_FSIZE, &initial_lim), SyscallSucceeds());
   139    auto cleanup = Cleanup([&initial_lim] {
   140      EXPECT_THAT(setrlimit(RLIMIT_FSIZE, &initial_lim), SyscallSucceeds());
   141    });
   142  
   143    // Try growing past the file size limit.
   144    sigset_t new_mask;
   145    sigemptyset(&new_mask);
   146    sigaddset(&new_mask, SIGXFSZ);
   147    sigprocmask(SIG_BLOCK, &new_mask, nullptr);
   148  
   149    struct rlimit setlim = {};
   150    setlim.rlim_cur = 1024;
   151    setlim.rlim_max = RLIM_INFINITY;
   152    ASSERT_THAT(setrlimit(RLIMIT_FSIZE, &setlim), SyscallSucceeds());
   153  
   154    EXPECT_THAT(fallocate(test_file_fd_.get(), 0, 0, 1025),
   155                SyscallFailsWithErrno(EFBIG));
   156  
   157    struct timespec timelimit = {};
   158    timelimit.tv_sec = 10;
   159    EXPECT_EQ(sigtimedwait(&new_mask, nullptr, &timelimit), SIGXFSZ);
   160    ASSERT_THAT(sigprocmask(SIG_UNBLOCK, &new_mask, nullptr), SyscallSucceeds());
   161  }
   162  
   163  TEST_F(AllocateTest, FallocateOtherFDs) {
   164    int fd;
   165    ASSERT_THAT(fd = timerfd_create(CLOCK_MONOTONIC, 0), SyscallSucceeds());
   166    auto timer_fd = FileDescriptor(fd);
   167    EXPECT_THAT(fallocate(timer_fd.get(), 0, 0, 10),
   168                SyscallFailsWithErrno(ENODEV));
   169  
   170    sigset_t mask;
   171    sigemptyset(&mask);
   172    ASSERT_THAT(fd = signalfd(-1, &mask, 0), SyscallSucceeds());
   173    auto sfd = FileDescriptor(fd);
   174    EXPECT_THAT(fallocate(sfd.get(), 0, 0, 10), SyscallFailsWithErrno(ENODEV));
   175  
   176    auto efd =
   177        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
   178    EXPECT_THAT(fallocate(efd.get(), 0, 0, 10), SyscallFailsWithErrno(ENODEV));
   179  
   180    auto sockfd = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0));
   181    EXPECT_THAT(fallocate(sockfd.get(), 0, 0, 10), SyscallFailsWithErrno(ENODEV));
   182  
   183    int socks[2];
   184    ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, socks),
   185                SyscallSucceeds());
   186    auto sock0 = FileDescriptor(socks[0]);
   187    auto sock1 = FileDescriptor(socks[1]);
   188    EXPECT_THAT(fallocate(sock0.get(), 0, 0, 10), SyscallFailsWithErrno(ENODEV));
   189  
   190    int pipefds[2];
   191    ASSERT_THAT(pipe(pipefds), SyscallSucceeds());
   192    EXPECT_THAT(fallocate(pipefds[1], 0, 0, 10), SyscallFailsWithErrno(ESPIPE));
   193    close(pipefds[0]);
   194    close(pipefds[1]);
   195  }
   196  
   197  }  // namespace
   198  }  // namespace testing
   199  }  // namespace gvisor