github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/access.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 <stdlib.h>
    18  #include <sys/stat.h>
    19  #include <sys/types.h>
    20  #include <unistd.h>
    21  
    22  #include "gtest/gtest.h"
    23  #include "test/util/capability_util.h"
    24  #include "test/util/fs_util.h"
    25  #include "test/util/temp_path.h"
    26  #include "test/util/test_util.h"
    27  
    28  using ::testing::Ge;
    29  
    30  namespace gvisor {
    31  namespace testing {
    32  
    33  namespace {
    34  
    35  class AccessTest : public ::testing::Test {
    36   public:
    37    std::string CreateTempFile(int perm) {
    38      const std::string path = NewTempAbsPath();
    39      const int fd = open(path.c_str(), O_CREAT | O_RDONLY, perm);
    40      TEST_PCHECK(fd > 0);
    41      TEST_PCHECK(close(fd) == 0);
    42      return path;
    43    }
    44  
    45   protected:
    46    // SetUp creates various configurations of files.
    47    void SetUp() override {
    48      // Move to the temporary directory. This allows us to reason more easily
    49      // about absolute and relative paths.
    50      ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds());
    51  
    52      // Create an empty file, standard permissions.
    53      relfile_ = NewTempRelPath();
    54      int fd;
    55      ASSERT_THAT(fd = open(relfile_.c_str(), O_CREAT | O_TRUNC, 0644),
    56                  SyscallSucceedsWithValue(Ge(0)));
    57      ASSERT_THAT(close(fd), SyscallSucceeds());
    58      absfile_ = GetAbsoluteTestTmpdir() + "/" + relfile_;
    59  
    60      // Create an empty directory, no writable permissions.
    61      absdir_ = NewTempAbsPath();
    62      reldir_ = JoinPath(Basename(absdir_), "");
    63      ASSERT_THAT(mkdir(reldir_.c_str(), 0555), SyscallSucceeds());
    64  
    65      // This file doesn't exist.
    66      relnone_ = NewTempRelPath();
    67      absnone_ = GetAbsoluteTestTmpdir() + "/" + relnone_;
    68    }
    69  
    70    // TearDown unlinks created files.
    71    void TearDown() override {
    72      ASSERT_THAT(unlink(absfile_.c_str()), SyscallSucceeds());
    73      ASSERT_THAT(rmdir(absdir_.c_str()), SyscallSucceeds());
    74    }
    75  
    76    std::string relfile_;
    77    std::string reldir_;
    78  
    79    std::string absfile_;
    80    std::string absdir_;
    81  
    82    std::string relnone_;
    83    std::string absnone_;
    84  };
    85  
    86  TEST_F(AccessTest, RelativeFile) {
    87    EXPECT_THAT(access(relfile_.c_str(), R_OK), SyscallSucceeds());
    88  }
    89  
    90  TEST_F(AccessTest, RelativeDir) {
    91    EXPECT_THAT(access(reldir_.c_str(), R_OK | X_OK), SyscallSucceeds());
    92  }
    93  
    94  TEST_F(AccessTest, AbsFile) {
    95    EXPECT_THAT(access(absfile_.c_str(), R_OK), SyscallSucceeds());
    96  }
    97  
    98  TEST_F(AccessTest, AbsDir) {
    99    EXPECT_THAT(access(absdir_.c_str(), R_OK | X_OK), SyscallSucceeds());
   100  }
   101  
   102  TEST_F(AccessTest, RelDoesNotExist) {
   103    EXPECT_THAT(access(relnone_.c_str(), R_OK), SyscallFailsWithErrno(ENOENT));
   104  }
   105  
   106  TEST_F(AccessTest, AbsDoesNotExist) {
   107    EXPECT_THAT(access(absnone_.c_str(), R_OK), SyscallFailsWithErrno(ENOENT));
   108  }
   109  
   110  TEST_F(AccessTest, InvalidMode) {
   111    EXPECT_THAT(access(relfile_.c_str(), 0xffffffff),
   112                SyscallFailsWithErrno(EINVAL));
   113  }
   114  
   115  TEST_F(AccessTest, NoPerms) {
   116    // Drop capabilities that allow us to override permissions. We must drop
   117    // PERMITTED because access() checks those instead of EFFECTIVE.
   118    ASSERT_NO_ERRNO(DropPermittedCapability(CAP_DAC_OVERRIDE));
   119    ASSERT_NO_ERRNO(DropPermittedCapability(CAP_DAC_READ_SEARCH));
   120  
   121    EXPECT_THAT(access(absdir_.c_str(), W_OK), SyscallFailsWithErrno(EACCES));
   122  }
   123  
   124  TEST_F(AccessTest, InvalidName) {
   125    EXPECT_THAT(access(reinterpret_cast<char*>(0x1234), W_OK),
   126                SyscallFailsWithErrno(EFAULT));
   127  }
   128  
   129  TEST_F(AccessTest, UsrReadOnly) {
   130    // Drop capabilities that allow us to override permissions. We must drop
   131    // PERMITTED because access() checks those instead of EFFECTIVE.
   132    ASSERT_NO_ERRNO(DropPermittedCapability(CAP_DAC_OVERRIDE));
   133    ASSERT_NO_ERRNO(DropPermittedCapability(CAP_DAC_READ_SEARCH));
   134  
   135    const std::string filename = CreateTempFile(0400);
   136    EXPECT_THAT(access(filename.c_str(), R_OK), SyscallSucceeds());
   137    EXPECT_THAT(access(filename.c_str(), W_OK), SyscallFailsWithErrno(EACCES));
   138    EXPECT_THAT(access(filename.c_str(), X_OK), SyscallFailsWithErrno(EACCES));
   139    EXPECT_THAT(unlink(filename.c_str()), SyscallSucceeds());
   140  }
   141  
   142  TEST_F(AccessTest, UsrReadExec) {
   143    // Drop capabilities that allow us to override permissions. We must drop
   144    // PERMITTED because access() checks those instead of EFFECTIVE.
   145    ASSERT_NO_ERRNO(DropPermittedCapability(CAP_DAC_OVERRIDE));
   146    ASSERT_NO_ERRNO(DropPermittedCapability(CAP_DAC_READ_SEARCH));
   147  
   148    const std::string filename = CreateTempFile(0500);
   149    EXPECT_THAT(access(filename.c_str(), R_OK | X_OK), SyscallSucceeds());
   150    EXPECT_THAT(access(filename.c_str(), W_OK), SyscallFailsWithErrno(EACCES));
   151    EXPECT_THAT(unlink(filename.c_str()), SyscallSucceeds());
   152  }
   153  
   154  TEST_F(AccessTest, UsrReadWrite) {
   155    const std::string filename = CreateTempFile(0600);
   156    EXPECT_THAT(access(filename.c_str(), R_OK | W_OK), SyscallSucceeds());
   157    EXPECT_THAT(access(filename.c_str(), X_OK), SyscallFailsWithErrno(EACCES));
   158    EXPECT_THAT(unlink(filename.c_str()), SyscallSucceeds());
   159  }
   160  
   161  TEST_F(AccessTest, UsrReadWriteExec) {
   162    const std::string filename = CreateTempFile(0700);
   163    EXPECT_THAT(access(filename.c_str(), R_OK | W_OK | X_OK), SyscallSucceeds());
   164    EXPECT_THAT(unlink(filename.c_str()), SyscallSucceeds());
   165  }
   166  
   167  }  // namespace
   168  
   169  }  // namespace testing
   170  }  // namespace gvisor