gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/open_create.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 <sys/stat.h> 18 #include <sys/types.h> 19 #include <unistd.h> 20 21 #include "gtest/gtest.h" 22 #include "test/util/capability_util.h" 23 #include "test/util/file_descriptor.h" 24 #include "test/util/fs_util.h" 25 #include "test/util/posix_error.h" 26 #include "test/util/temp_path.h" 27 #include "test/util/temp_umask.h" 28 #include "test/util/test_util.h" 29 30 namespace gvisor { 31 namespace testing { 32 33 namespace { 34 TEST(CreateTest, TmpFile) { 35 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 36 EXPECT_NO_ERRNO(Open(JoinPath(dir.path(), "a"), O_RDWR | O_CREAT, 0666)); 37 } 38 39 TEST(CreateTest, ExistingFile) { 40 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 41 auto path = JoinPath(dir.path(), "ExistingFile"); 42 EXPECT_NO_ERRNO(Open(path, O_RDWR | O_CREAT, 0666)); 43 EXPECT_NO_ERRNO(Open(path, O_RDWR | O_CREAT, 0666)); 44 } 45 46 TEST(CreateTest, CreateAtFile) { 47 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 48 auto dirfd = ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_DIRECTORY, 0666)); 49 int fd; 50 EXPECT_THAT(fd = openat(dirfd.get(), "CreateAtFile", O_RDWR | O_CREAT, 0666), 51 SyscallSucceeds()); 52 EXPECT_THAT(close(fd), SyscallSucceeds()); 53 } 54 55 TEST(CreateTest, HonorsUmask) { 56 const DisableSave ds; // file cannot be re-opened as writable. 57 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 58 TempUmask mask(0222); 59 auto fd = ASSERT_NO_ERRNO_AND_VALUE( 60 Open(JoinPath(dir.path(), "UmaskedFile"), O_RDWR | O_CREAT, 0666)); 61 struct stat statbuf; 62 ASSERT_THAT(fstat(fd.get(), &statbuf), SyscallSucceeds()); 63 EXPECT_EQ(0444, statbuf.st_mode & 0777); 64 } 65 66 TEST(CreateTest, CreateExclusively) { 67 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 68 auto path = JoinPath(dir.path(), "foo"); 69 EXPECT_NO_ERRNO(Open(path, O_CREAT | O_RDWR, 0644)); 70 EXPECT_THAT(open(path.c_str(), O_CREAT | O_EXCL | O_RDWR, 0644), 71 SyscallFailsWithErrno(EEXIST)); 72 } 73 74 TEST(CreateTest, CreatWithOTrunc) { 75 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 76 ASSERT_THAT(open(dir.path().c_str(), O_CREAT | O_TRUNC, 0666), 77 SyscallFailsWithErrno(EISDIR)); 78 } 79 80 TEST(CreateTest, CreatDirWithOTruncAndReadOnly) { 81 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 82 ASSERT_THAT(open(dir.path().c_str(), O_CREAT | O_TRUNC | O_RDONLY, 0666), 83 SyscallFailsWithErrno(EISDIR)); 84 } 85 86 TEST(CreateTest, CreatFileWithOTruncAndReadOnly) { 87 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 88 auto path = JoinPath(dir.path(), "foo"); 89 ASSERT_NO_ERRNO(Open(path, O_RDWR | O_CREAT, 0666)); 90 ASSERT_NO_ERRNO(Open(path, O_CREAT | O_TRUNC | O_RDONLY, 0666)); 91 } 92 93 TEST(CreateTest, CreateFailsOnDirWithoutWritePerms) { 94 // Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to 95 // always override directory permissions. 96 AutoCapability cap(CAP_DAC_OVERRIDE, false); 97 98 auto parent = ASSERT_NO_ERRNO_AND_VALUE( 99 TempPath::CreateDirWith(GetAbsoluteTestTmpdir(), 0555)); 100 auto file = JoinPath(parent.path(), "foo"); 101 ASSERT_THAT(open(file.c_str(), O_CREAT | O_RDWR, 0644), 102 SyscallFailsWithErrno(EACCES)); 103 } 104 105 // A file originally created RW, but opened RO can later be opened RW. 106 // Regression test for b/65385065. 107 TEST(CreateTest, OpenCreateROThenRW) { 108 TempPath file(NewTempAbsPath()); 109 110 // Create a RW file, but only open it RO. 111 FileDescriptor fd1 = ASSERT_NO_ERRNO_AND_VALUE( 112 Open(file.path(), O_CREAT | O_EXCL | O_RDONLY, 0644)); 113 114 // Now get a RW FD. 115 FileDescriptor fd2 = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDWR)); 116 117 // fd1 is not writable, but fd2 is. 118 char c = 'a'; 119 EXPECT_THAT(WriteFd(fd1.get(), &c, 1), SyscallFailsWithErrno(EBADF)); 120 EXPECT_THAT(WriteFd(fd2.get(), &c, 1), SyscallSucceedsWithValue(1)); 121 } 122 123 TEST(CreateTest, ChmodReadToWriteBetweenOpens) { 124 // Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to 125 // override file read/write permissions. CAP_DAC_READ_SEARCH needs to be 126 // cleared for the same reason. 127 AutoCapability cap1(CAP_DAC_OVERRIDE, false); 128 AutoCapability cap2(CAP_DAC_READ_SEARCH, false); 129 130 const TempPath file = 131 ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileMode(0400)); 132 133 const FileDescriptor rfd = 134 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY)); 135 136 // Cannot restore after making permissions more restrictive. 137 const DisableSave ds; 138 ASSERT_THAT(fchmod(rfd.get(), 0200), SyscallSucceeds()); 139 140 EXPECT_THAT(open(file.path().c_str(), O_RDONLY), 141 SyscallFailsWithErrno(EACCES)); 142 143 const FileDescriptor wfd = 144 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY)); 145 146 char c = 'x'; 147 EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 148 c = 0; 149 EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 150 EXPECT_EQ(c, 'x'); 151 } 152 153 TEST(CreateTest, ChmodWriteToReadBetweenOpens) { 154 // Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to 155 // override file read/write permissions. 156 AutoCapability cap(CAP_DAC_OVERRIDE, false); 157 158 const TempPath file = 159 ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileMode(0200)); 160 161 const FileDescriptor wfd = 162 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY)); 163 164 // Cannot restore after making permissions more restrictive. 165 const DisableSave ds; 166 ASSERT_THAT(fchmod(wfd.get(), 0400), SyscallSucceeds()); 167 168 EXPECT_THAT(open(file.path().c_str(), O_WRONLY), 169 SyscallFailsWithErrno(EACCES)); 170 171 const FileDescriptor rfd = 172 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY)); 173 174 char c = 'x'; 175 EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 176 c = 0; 177 EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 178 EXPECT_EQ(c, 'x'); 179 } 180 181 TEST(CreateTest, CreateWithReadFlagNotAllowedByMode) { 182 // The only time we can open a file with flags forbidden by its permissions 183 // is when we are creating the file. We cannot re-open with the same flags, 184 // so we cannot restore an fd obtained from such an operation. 185 const DisableSave ds; 186 187 // Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to 188 // override file read/write permissions. CAP_DAC_READ_SEARCH needs to be 189 // cleared for the same reason. 190 AutoCapability cap1(CAP_DAC_OVERRIDE, false); 191 AutoCapability cap2(CAP_DAC_READ_SEARCH, false); 192 193 // Create and open a file with read flag but without read permissions. 194 const std::string path = NewTempAbsPath(); 195 const FileDescriptor rfd = 196 ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_CREAT | O_RDONLY, 0222)); 197 198 EXPECT_THAT(open(path.c_str(), O_RDONLY), SyscallFailsWithErrno(EACCES)); 199 const FileDescriptor wfd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_WRONLY)); 200 201 char c = 'x'; 202 EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 203 c = 0; 204 EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 205 EXPECT_EQ(c, 'x'); 206 } 207 208 TEST(CreateTest, CreateWithWriteFlagNotAllowedByMode) { 209 // The only time we can open a file with flags forbidden by its permissions 210 // is when we are creating the file. We cannot re-open with the same flags, 211 // so we cannot restore an fd obtained from such an operation. 212 const DisableSave ds; 213 214 // Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to 215 // override file read/write permissions. 216 AutoCapability cap(CAP_DAC_OVERRIDE, false); 217 218 // Create and open a file with write flag but without write permissions. 219 const std::string path = NewTempAbsPath(); 220 const FileDescriptor wfd = 221 ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_CREAT | O_WRONLY, 0444)); 222 223 EXPECT_THAT(open(path.c_str(), O_WRONLY), SyscallFailsWithErrno(EACCES)); 224 const FileDescriptor rfd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_RDONLY)); 225 226 char c = 'x'; 227 EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 228 c = 0; 229 EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1)); 230 EXPECT_EQ(c, 'x'); 231 } 232 233 } // namespace 234 235 } // namespace testing 236 } // namespace gvisor