gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/open.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 <linux/capability.h> 18 #include <sys/stat.h> 19 #include <sys/types.h> 20 #include <unistd.h> 21 22 #include <cstdlib> 23 #include <memory> 24 25 #include "gmock/gmock.h" 26 #include "gtest/gtest.h" 27 #include "absl/memory/memory.h" 28 #include "absl/strings/string_view.h" 29 #include "test/syscalls/linux/file_base.h" 30 #include "test/util/capability_util.h" 31 #include "test/util/cleanup.h" 32 #include "test/util/file_descriptor.h" 33 #include "test/util/fs_util.h" 34 #include "test/util/posix_error.h" 35 #include "test/util/temp_path.h" 36 #include "test/util/test_util.h" 37 #include "test/util/thread_util.h" 38 39 namespace gvisor { 40 namespace testing { 41 42 namespace { 43 44 // This test is currently very rudimentary. 45 // 46 // There are plenty of extra cases to cover once the sentry supports them. 47 // 48 // Different types of opens: 49 // * O_CREAT 50 // * O_DIRECTORY 51 // * O_NOFOLLOW 52 // * O_PATH 53 // 54 // Special operations on open: 55 // * O_EXCL 56 // 57 // Special files: 58 // * Blocking behavior for a named pipe. 59 // 60 // Different errors: 61 // * EACCES 62 // * EEXIST 63 // * ENAMETOOLONG 64 // * ELOOP 65 // * ENOTDIR 66 // * EPERM 67 class OpenTest : public FileTest { 68 void SetUp() override { 69 FileTest::SetUp(); 70 71 ASSERT_THAT( 72 write(test_file_fd_.get(), test_data_.c_str(), test_data_.length()), 73 SyscallSucceedsWithValue(test_data_.length())); 74 EXPECT_THAT(lseek(test_file_fd_.get(), 0, SEEK_SET), SyscallSucceeds()); 75 } 76 77 public: 78 const std::string test_data_ = "hello world\n"; 79 }; 80 81 TEST_F(OpenTest, OTrunc) { 82 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 83 ASSERT_THAT(open(dir.path().c_str(), O_TRUNC, 0666), 84 SyscallFailsWithErrno(EISDIR)); 85 } 86 87 TEST_F(OpenTest, OTruncAndReadOnlyDir) { 88 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 89 ASSERT_THAT(open(dir.path().c_str(), O_TRUNC | O_RDONLY, 0666), 90 SyscallFailsWithErrno(EISDIR)); 91 } 92 93 TEST_F(OpenTest, OTruncAndReadOnlyFile) { 94 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 95 auto path = JoinPath(dir.path(), "foo"); 96 EXPECT_NO_ERRNO(Open(path, O_RDWR | O_CREAT, 0666)); 97 EXPECT_NO_ERRNO(Open(path, O_TRUNC | O_RDONLY, 0666)); 98 } 99 100 TEST_F(OpenTest, OCreateDirectory) { 101 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 102 103 // Normal case: existing directory. 104 ASSERT_THAT(open(dir.path().c_str(), O_RDONLY | O_CREAT, 0666), 105 SyscallFailsWithErrno(EISDIR)); 106 // Trailing separator on existing directory. 107 ASSERT_THAT(open((dir.path() + "/").c_str(), O_RDONLY | O_CREAT, 0666), 108 SyscallFailsWithErrno(EISDIR)); 109 // Trailing separator on non-existing directory. 110 ASSERT_THAT(open((JoinPath(dir.path(), "non-existent") + "/").c_str(), 111 O_RDONLY | O_CREAT, 0666), 112 SyscallFailsWithErrno(EISDIR)); 113 // "." special case. 114 ASSERT_THAT(open(JoinPath(dir.path(), ".").c_str(), O_RDONLY | O_CREAT, 0666), 115 SyscallFailsWithErrno(EISDIR)); 116 } 117 118 TEST_F(OpenTest, MustCreateExisting) { 119 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 120 121 // Existing directory. 122 ASSERT_THAT(open(dir.path().c_str(), O_RDWR | O_CREAT | O_EXCL, 0666), 123 SyscallFailsWithErrno(EEXIST)); 124 125 // Existing file. 126 auto newFile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path())); 127 ASSERT_THAT(open(newFile.path().c_str(), O_RDWR | O_CREAT | O_EXCL, 0666), 128 SyscallFailsWithErrno(EEXIST)); 129 } 130 131 TEST_F(OpenTest, ReadOnly) { 132 char buf; 133 const FileDescriptor ro_file = 134 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDONLY)); 135 136 EXPECT_THAT(read(ro_file.get(), &buf, 1), SyscallSucceedsWithValue(1)); 137 EXPECT_THAT(lseek(ro_file.get(), 0, SEEK_SET), SyscallSucceeds()); 138 EXPECT_THAT(write(ro_file.get(), &buf, 1), SyscallFailsWithErrno(EBADF)); 139 } 140 141 TEST_F(OpenTest, WriteOnly) { 142 char buf; 143 const FileDescriptor wo_file = 144 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_WRONLY)); 145 146 EXPECT_THAT(read(wo_file.get(), &buf, 1), SyscallFailsWithErrno(EBADF)); 147 EXPECT_THAT(lseek(wo_file.get(), 0, SEEK_SET), SyscallSucceeds()); 148 EXPECT_THAT(write(wo_file.get(), &buf, 1), SyscallSucceedsWithValue(1)); 149 } 150 151 TEST_F(OpenTest, CreateWithAppend) { 152 std::string data = "text"; 153 std::string new_file = NewTempAbsPath(); 154 const FileDescriptor file = ASSERT_NO_ERRNO_AND_VALUE( 155 Open(new_file, O_WRONLY | O_APPEND | O_CREAT, 0666)); 156 EXPECT_THAT(write(file.get(), data.c_str(), data.size()), 157 SyscallSucceedsWithValue(data.size())); 158 EXPECT_THAT(lseek(file.get(), 0, SEEK_SET), SyscallSucceeds()); 159 EXPECT_THAT(write(file.get(), data.c_str(), data.size()), 160 SyscallSucceedsWithValue(data.size())); 161 162 // Check that the size of the file is correct and that the offset has been 163 // incremented to that size. 164 struct stat s0; 165 EXPECT_THAT(fstat(file.get(), &s0), SyscallSucceeds()); 166 EXPECT_EQ(s0.st_size, 2 * data.size()); 167 EXPECT_THAT(lseek(file.get(), 0, SEEK_CUR), 168 SyscallSucceedsWithValue(2 * data.size())); 169 } 170 171 TEST_F(OpenTest, ReadWrite) { 172 char buf; 173 const FileDescriptor rw_file = 174 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR)); 175 176 EXPECT_THAT(read(rw_file.get(), &buf, 1), SyscallSucceedsWithValue(1)); 177 EXPECT_THAT(lseek(rw_file.get(), 0, SEEK_SET), SyscallSucceeds()); 178 EXPECT_THAT(write(rw_file.get(), &buf, 1), SyscallSucceedsWithValue(1)); 179 } 180 181 TEST_F(OpenTest, RelPath) { 182 auto name = std::string(Basename(test_file_name_)); 183 184 ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds()); 185 const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name, O_RDONLY)); 186 } 187 188 TEST_F(OpenTest, AbsPath) { 189 const FileDescriptor fd = 190 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDONLY)); 191 } 192 193 TEST_F(OpenTest, AtRelPath) { 194 auto name = std::string(Basename(test_file_name_)); 195 const FileDescriptor dirfd = ASSERT_NO_ERRNO_AND_VALUE( 196 Open(GetAbsoluteTestTmpdir(), O_RDONLY | O_DIRECTORY)); 197 const FileDescriptor fd = 198 ASSERT_NO_ERRNO_AND_VALUE(OpenAt(dirfd.get(), name, O_RDONLY)); 199 } 200 201 TEST_F(OpenTest, AtAbsPath) { 202 const FileDescriptor dirfd = ASSERT_NO_ERRNO_AND_VALUE( 203 Open(GetAbsoluteTestTmpdir(), O_RDONLY | O_DIRECTORY)); 204 const FileDescriptor fd = 205 ASSERT_NO_ERRNO_AND_VALUE(OpenAt(dirfd.get(), test_file_name_, O_RDONLY)); 206 } 207 208 TEST_F(OpenTest, OpenNoFollowSymlink) { 209 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 210 const std::string link_path = JoinPath(dir.path().c_str(), "link"); 211 ASSERT_THAT(symlink(test_file_name_.c_str(), link_path.c_str()), 212 SyscallSucceeds()); 213 auto cleanup = Cleanup([link_path]() { 214 EXPECT_THAT(unlink(link_path.c_str()), SyscallSucceeds()); 215 }); 216 217 // Open will succeed without O_NOFOLLOW and fails with O_NOFOLLOW. 218 const FileDescriptor fd2 = 219 ASSERT_NO_ERRNO_AND_VALUE(Open(link_path, O_RDONLY)); 220 ASSERT_THAT(open(link_path.c_str(), O_RDONLY | O_NOFOLLOW), 221 SyscallFailsWithErrno(ELOOP)); 222 } 223 224 TEST_F(OpenTest, OpenNoFollowStillFollowsLinksInPath) { 225 // We will create the following structure: 226 // tmp_folder/real_folder/file 227 // tmp_folder/sym_folder -> tmp_folder/real_folder 228 // 229 // We will then open tmp_folder/sym_folder/file with O_NOFOLLOW and it 230 // should succeed as O_NOFOLLOW only applies to the final path component. 231 auto tmp_path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 232 auto sym_path = ASSERT_NO_ERRNO_AND_VALUE( 233 TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), tmp_path.path())); 234 auto file_path = 235 ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(tmp_path.path())); 236 237 auto path_via_symlink = JoinPath(sym_path.path(), Basename(file_path.path())); 238 const FileDescriptor fd2 = 239 ASSERT_NO_ERRNO_AND_VALUE(Open(path_via_symlink, O_RDONLY | O_NOFOLLOW)); 240 } 241 242 // Test that open(2) can follow symlinks that point back to the same tree. 243 // Test sets up files as follows: 244 // root/child/symlink => redirects to ../.. 245 // root/child/target => regular file 246 // 247 // open("root/child/symlink/root/child/file") 248 TEST_F(OpenTest, SymlinkRecurse) { 249 auto root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 250 auto child = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(root.path())); 251 auto symlink = ASSERT_NO_ERRNO_AND_VALUE( 252 TempPath::CreateSymlinkTo(child.path(), "../..")); 253 auto target = ASSERT_NO_ERRNO_AND_VALUE( 254 TempPath::CreateFileWith(child.path(), "abc", 0644)); 255 auto path_via_symlink = 256 JoinPath(symlink.path(), Basename(root.path()), Basename(child.path()), 257 Basename(target.path())); 258 const auto contents = 259 ASSERT_NO_ERRNO_AND_VALUE(GetContents(path_via_symlink)); 260 ASSERT_EQ(contents, "abc"); 261 } 262 263 TEST_F(OpenTest, Fault) { 264 char* totally_not_null = nullptr; 265 ASSERT_THAT(open(totally_not_null, O_RDONLY), SyscallFailsWithErrno(EFAULT)); 266 } 267 268 TEST_F(OpenTest, AppendOnly) { 269 // First write some data to the fresh file. 270 const int64_t kBufSize = 1024; 271 std::vector<char> buf(kBufSize, 'a'); 272 273 FileDescriptor fd0 = ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR)); 274 275 std::fill(buf.begin(), buf.end(), 'a'); 276 EXPECT_THAT(WriteFd(fd0.get(), buf.data(), buf.size()), 277 SyscallSucceedsWithValue(buf.size())); 278 fd0.reset(); // Close the file early. 279 280 // Next get two handles to the same file. We open two files because we want 281 // to make sure that appending is respected between them. 282 const FileDescriptor fd1 = 283 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR | O_APPEND)); 284 EXPECT_THAT(lseek(fd1.get(), 0, SEEK_CUR), SyscallSucceedsWithValue(0)); 285 286 const FileDescriptor fd2 = 287 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR | O_APPEND)); 288 EXPECT_THAT(lseek(fd2.get(), 0, SEEK_CUR), SyscallSucceedsWithValue(0)); 289 290 // Then try to write to the first fd and make sure the bytes are appended. 291 EXPECT_THAT(WriteFd(fd1.get(), buf.data(), buf.size()), 292 SyscallSucceedsWithValue(buf.size())); 293 294 // Check that the size of the file is correct and that the offset has been 295 // incremented to that size. 296 struct stat s0; 297 EXPECT_THAT(fstat(fd1.get(), &s0), SyscallSucceeds()); 298 EXPECT_EQ(s0.st_size, kBufSize * 2); 299 EXPECT_THAT(lseek(fd1.get(), 0, SEEK_CUR), 300 SyscallSucceedsWithValue(kBufSize * 2)); 301 302 // Then try to write to the second fd and make sure the bytes are appended. 303 EXPECT_THAT(WriteFd(fd2.get(), buf.data(), buf.size()), 304 SyscallSucceedsWithValue(buf.size())); 305 306 // Check that the size of the file is correct and that the offset has been 307 // incremented to that size. 308 struct stat s1; 309 EXPECT_THAT(fstat(fd2.get(), &s1), SyscallSucceeds()); 310 EXPECT_EQ(s1.st_size, kBufSize * 3); 311 EXPECT_THAT(lseek(fd2.get(), 0, SEEK_CUR), 312 SyscallSucceedsWithValue(kBufSize * 3)); 313 } 314 315 TEST_F(OpenTest, AppendConcurrentWrite) { 316 constexpr int kThreadCount = 5; 317 constexpr int kBytesPerThread = 10000; 318 std::unique_ptr<ScopedThread> threads[kThreadCount]; 319 320 // In case of the uncached policy, we expect that a file system can be changed 321 // externally, so we create a new inode each time when we open a file and we 322 // can't guarantee that writes to files with O_APPEND will work correctly. 323 SKIP_IF(getenv("GVISOR_GOFER_UNCACHED")); 324 SKIP_IF(absl::NullSafeStringView(getenv("GVISOR_FUSE_TEST")) == "TRUE"); 325 326 EXPECT_THAT(truncate(test_file_name_.c_str(), 0), SyscallSucceeds()); 327 328 std::string filename = test_file_name_; 329 DisableSave ds; // Too many syscalls. 330 // Start kThreadCount threads which will write concurrently into the same 331 // file. 332 for (int i = 0; i < kThreadCount; i++) { 333 threads[i] = std::make_unique<ScopedThread>([filename]() { 334 const FileDescriptor fd = 335 ASSERT_NO_ERRNO_AND_VALUE(Open(filename, O_RDWR | O_APPEND)); 336 337 for (int j = 0; j < kBytesPerThread; j++) { 338 EXPECT_THAT(WriteFd(fd.get(), &j, 1), SyscallSucceedsWithValue(1)); 339 } 340 }); 341 } 342 for (int i = 0; i < kThreadCount; i++) { 343 threads[i]->Join(); 344 } 345 346 // Check that the size of the file is correct. 347 struct stat st; 348 EXPECT_THAT(stat(test_file_name_.c_str(), &st), SyscallSucceeds()); 349 EXPECT_EQ(st.st_size, kThreadCount * kBytesPerThread); 350 } 351 352 TEST_F(OpenTest, Truncate) { 353 { 354 // First write some data to the new file and close it. 355 FileDescriptor fd0 = 356 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_WRONLY)); 357 std::vector<char> orig(10, 'a'); 358 EXPECT_THAT(WriteFd(fd0.get(), orig.data(), orig.size()), 359 SyscallSucceedsWithValue(orig.size())); 360 } 361 362 // Then open with truncate and verify that offset is set to 0. 363 const FileDescriptor fd1 = 364 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR | O_TRUNC)); 365 EXPECT_THAT(lseek(fd1.get(), 0, SEEK_CUR), SyscallSucceedsWithValue(0)); 366 367 // Then write less data to the file and ensure the old content is gone. 368 std::vector<char> want(5, 'b'); 369 EXPECT_THAT(WriteFd(fd1.get(), want.data(), want.size()), 370 SyscallSucceedsWithValue(want.size())); 371 372 struct stat stat; 373 EXPECT_THAT(fstat(fd1.get(), &stat), SyscallSucceeds()); 374 EXPECT_EQ(stat.st_size, want.size()); 375 EXPECT_THAT(lseek(fd1.get(), 0, SEEK_CUR), 376 SyscallSucceedsWithValue(want.size())); 377 378 // Read the data and ensure only the latest write is in the file. 379 std::vector<char> got(want.size() + 1, 'c'); 380 ASSERT_THAT(pread(fd1.get(), got.data(), got.size(), 0), 381 SyscallSucceedsWithValue(want.size())); 382 EXPECT_EQ(memcmp(want.data(), got.data(), want.size()), 0) 383 << "rbuf=" << got.data(); 384 EXPECT_EQ(got.back(), 'c'); // Last byte should not have been modified. 385 } 386 387 TEST_F(OpenTest, NameTooLong) { 388 char buf[4097] = {}; 389 memset(buf, 'a', 4097); 390 EXPECT_THAT(open(buf, O_RDONLY), SyscallFailsWithErrno(ENAMETOOLONG)); 391 } 392 393 TEST_F(OpenTest, DotsFromRoot) { 394 const FileDescriptor rootfd = 395 ASSERT_NO_ERRNO_AND_VALUE(Open("/", O_RDONLY | O_DIRECTORY)); 396 const FileDescriptor other_rootfd = 397 ASSERT_NO_ERRNO_AND_VALUE(OpenAt(rootfd.get(), "..", O_RDONLY)); 398 } 399 400 TEST_F(OpenTest, DirectoryWritableFails) { 401 ASSERT_THAT(open(GetAbsoluteTestTmpdir().c_str(), O_RDWR), 402 SyscallFailsWithErrno(EISDIR)); 403 } 404 405 TEST_F(OpenTest, DirectoryDirectFails) { 406 ASSERT_THAT(open(GetAbsoluteTestTmpdir().c_str(), O_RDONLY | O_DIRECT), 407 SyscallFailsWithErrno(EINVAL)); 408 } 409 410 TEST_F(OpenTest, FileNotDirectory) { 411 // Create a file and try to open it with O_DIRECTORY. 412 auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 413 ASSERT_THAT(open(file.path().c_str(), O_RDONLY | O_DIRECTORY), 414 SyscallFailsWithErrno(ENOTDIR)); 415 } 416 417 TEST_F(OpenTest, SymlinkDirectory) { 418 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 419 std::string link = NewTempAbsPath(); 420 ASSERT_THAT(symlink(dir.path().c_str(), link.c_str()), SyscallSucceeds()); 421 ASSERT_NO_ERRNO(Open(link, O_RDONLY | O_DIRECTORY)); 422 } 423 424 TEST_F(OpenTest, Null) { 425 char c = '\0'; 426 ASSERT_THAT(open(&c, O_RDONLY), SyscallFailsWithErrno(ENOENT)); 427 } 428 429 // NOTE(b/119785738): While the man pages specify that this behavior should be 430 // undefined, Linux truncates the file on opening read only if we have write 431 // permission, so we will too. 432 TEST_F(OpenTest, CanTruncateReadOnly) { 433 const FileDescriptor fd1 = 434 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDONLY | O_TRUNC)); 435 436 struct stat stat; 437 EXPECT_THAT(fstat(fd1.get(), &stat), SyscallSucceeds()); 438 EXPECT_EQ(stat.st_size, 0); 439 } 440 441 // If we don't have read permission on the file, opening with 442 // O_TRUNC should fail. 443 TEST_F(OpenTest, CanTruncateReadOnlyNoWritePermission) { 444 // Drop capabilities that allow us to override file permissions. 445 AutoCapability cap(CAP_DAC_OVERRIDE, false); 446 447 const DisableSave ds; // Permissions are dropped. 448 ASSERT_THAT(chmod(test_file_name_.c_str(), S_IRUSR | S_IRGRP), 449 SyscallSucceeds()); 450 451 ASSERT_THAT(open(test_file_name_.c_str(), O_RDONLY | O_TRUNC), 452 SyscallFailsWithErrno(EACCES)); 453 454 const FileDescriptor fd1 = 455 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDONLY)); 456 457 struct stat stat; 458 EXPECT_THAT(fstat(fd1.get(), &stat), SyscallSucceeds()); 459 EXPECT_EQ(stat.st_size, test_data_.size()); 460 } 461 462 // If we don't have read permission but have write permission, opening O_WRONLY 463 // and O_TRUNC should succeed. 464 TEST_F(OpenTest, CanTruncateWriteOnlyNoReadPermission) { 465 const DisableSave ds; // Permissions are dropped. 466 467 EXPECT_THAT(fchmod(test_file_fd_.get(), S_IWUSR | S_IWGRP), 468 SyscallSucceeds()); 469 470 const FileDescriptor fd1 = 471 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_WRONLY | O_TRUNC)); 472 473 EXPECT_THAT(fchmod(test_file_fd_.get(), S_IRUSR | S_IRGRP), 474 SyscallSucceeds()); 475 476 const FileDescriptor fd2 = 477 ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDONLY)); 478 479 struct stat stat; 480 EXPECT_THAT(fstat(fd2.get(), &stat), SyscallSucceeds()); 481 EXPECT_EQ(stat.st_size, 0); 482 } 483 484 TEST_F(OpenTest, CanTruncateWithStrangePermissions) { 485 AutoCapability cap1(CAP_DAC_OVERRIDE, false); 486 AutoCapability cap2(CAP_DAC_READ_SEARCH, false); 487 const DisableSave ds; // Permissions are dropped. 488 std::string path = NewTempAbsPath(); 489 // Create a file without user permissions. 490 EXPECT_NO_ERRNO(Open(path, O_CREAT | O_TRUNC | O_WRONLY, 055)); 491 492 // Cannot open file because we are owner and have no permissions set. 493 EXPECT_THAT(open(path.c_str(), O_RDONLY), SyscallFailsWithErrno(EACCES)); 494 495 // We *can* chmod the file, because we are the owner. 496 EXPECT_THAT(chmod(path.c_str(), 0755), SyscallSucceeds()); 497 498 // Now we can open the file again. 499 EXPECT_NO_ERRNO(Open(path, O_RDWR)); 500 } 501 502 TEST_F(OpenTest, OpenNonDirectoryWithTrailingSlash) { 503 const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 504 const std::string bad_path = file.path() + "/"; 505 EXPECT_THAT(open(bad_path.c_str(), O_RDONLY), SyscallFailsWithErrno(ENOTDIR)); 506 } 507 508 TEST_F(OpenTest, OpenWithStrangeFlags) { 509 const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 510 const FileDescriptor fd = 511 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY | O_RDWR)); 512 EXPECT_THAT(write(fd.get(), "x", 1), SyscallFailsWithErrno(EBADF)); 513 char c; 514 EXPECT_THAT(read(fd.get(), &c, 1), SyscallFailsWithErrno(EBADF)); 515 } 516 517 TEST_F(OpenTest, OpenWithOpath) { 518 AutoCapability cap1(CAP_DAC_OVERRIDE, false); 519 AutoCapability cap2(CAP_DAC_READ_SEARCH, false); 520 const DisableSave ds; // Permissions are dropped. 521 std::string path = NewTempAbsPath(); 522 523 // Create a file without user permissions. 524 const FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE( 525 Open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 055)); 526 527 // Cannot open file as read only because we are owner and have no permissions 528 // set. 529 EXPECT_THAT(open(path.c_str(), O_RDONLY), SyscallFailsWithErrno(EACCES)); 530 531 // Can open file with O_PATH because don't need permissions on the object when 532 // opening with O_PATH. 533 ASSERT_NO_ERRNO(Open(path, O_PATH)); 534 } 535 536 // NOTE(b/236445327): Regression test. Opening a non-directory with O_PATH and 537 // O_DIRECTORY should fail with ENOTDIR. 538 TEST_F(OpenTest, OPathWithODirectory) { 539 auto newFile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 540 EXPECT_THAT(open(newFile.path().c_str(), O_RDONLY | O_DIRECTORY | O_PATH), 541 SyscallFailsWithErrno(ENOTDIR)); 542 } 543 544 } // namespace 545 546 } // namespace testing 547 } // namespace gvisor