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