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