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