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