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