gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/mkdir.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 <fcntl.h> 16 #include <sys/stat.h> 17 #include <sys/types.h> 18 #include <unistd.h> 19 20 #include "gtest/gtest.h" 21 #include "test/util/capability_util.h" 22 #include "test/util/fs_util.h" 23 #include "test/util/temp_path.h" 24 #include "test/util/temp_umask.h" 25 #include "test/util/test_util.h" 26 27 namespace gvisor { 28 namespace testing { 29 30 namespace { 31 32 class MkdirTest : public ::testing::Test { 33 protected: 34 // SetUp creates various configurations of files. 35 void SetUp() override { dirname_ = NewTempAbsPath(); } 36 37 // TearDown unlinks created files. 38 void TearDown() override { 39 EXPECT_THAT(rmdir(dirname_.c_str()), SyscallSucceeds()); 40 } 41 42 std::string dirname_; 43 }; 44 45 TEST_F(MkdirTest, CanCreateWritableDir) { 46 ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); 47 std::string filename = JoinPath(dirname_, "anything"); 48 int fd; 49 ASSERT_THAT(fd = open(filename.c_str(), O_RDWR | O_CREAT, 0666), 50 SyscallSucceeds()); 51 EXPECT_THAT(close(fd), SyscallSucceeds()); 52 ASSERT_THAT(unlink(filename.c_str()), SyscallSucceeds()); 53 } 54 55 TEST_F(MkdirTest, HonorsUmask) { 56 constexpr mode_t kMask = 0111; 57 TempUmask mask(kMask); 58 ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); 59 struct stat statbuf; 60 ASSERT_THAT(stat(dirname_.c_str(), &statbuf), SyscallSucceeds()); 61 EXPECT_EQ(0777 & ~kMask, statbuf.st_mode & 0777); 62 } 63 64 TEST_F(MkdirTest, HonorsUmask2) { 65 constexpr mode_t kMask = 0142; 66 TempUmask mask(kMask); 67 ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); 68 struct stat statbuf; 69 ASSERT_THAT(stat(dirname_.c_str(), &statbuf), SyscallSucceeds()); 70 EXPECT_EQ(0777 & ~kMask, statbuf.st_mode & 0777); 71 } 72 73 TEST_F(MkdirTest, FailsOnDirWithoutWritePerms) { 74 // Drop capabilities that allow us to override file and directory permissions. 75 AutoCapability cap1(CAP_DAC_OVERRIDE, false); 76 AutoCapability cap2(CAP_DAC_READ_SEARCH, false); 77 78 ASSERT_THAT(mkdir(dirname_.c_str(), 0555), SyscallSucceeds()); 79 auto dir = JoinPath(dirname_.c_str(), "foo"); 80 EXPECT_THAT(mkdir(dir.c_str(), 0777), SyscallFailsWithErrno(EACCES)); 81 EXPECT_THAT(open(JoinPath(dirname_, "file").c_str(), O_RDWR | O_CREAT, 0666), 82 SyscallFailsWithErrno(EACCES)); 83 } 84 85 TEST_F(MkdirTest, DirAlreadyExists) { 86 // Drop capabilities that allow us to override file and directory permissions. 87 AutoCapability cap1(CAP_DAC_OVERRIDE, false); 88 AutoCapability cap2(CAP_DAC_READ_SEARCH, false); 89 90 ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); 91 auto dir = JoinPath(dirname_.c_str(), "foo"); 92 EXPECT_THAT(mkdir(dir.c_str(), 0777), SyscallSucceeds()); 93 94 struct { 95 int mode; 96 int err; 97 } tests[] = { 98 {.mode = 0000, .err = EACCES}, // No perm 99 {.mode = 0100, .err = EEXIST}, // Exec only 100 {.mode = 0200, .err = EACCES}, // Write only 101 {.mode = 0300, .err = EEXIST}, // Write+exec 102 {.mode = 0400, .err = EACCES}, // Read only 103 {.mode = 0500, .err = EEXIST}, // Read+exec 104 {.mode = 0600, .err = EACCES}, // Read+write 105 {.mode = 0700, .err = EEXIST}, // All 106 }; 107 for (const auto& t : tests) { 108 printf("mode: 0%o\n", t.mode); 109 EXPECT_THAT(chmod(dirname_.c_str(), t.mode), SyscallSucceeds()); 110 EXPECT_THAT(mkdir(dir.c_str(), 0777), SyscallFailsWithErrno(t.err)); 111 } 112 113 // Clean up. 114 EXPECT_THAT(chmod(dirname_.c_str(), 0777), SyscallSucceeds()); 115 ASSERT_THAT(rmdir(dir.c_str()), SyscallSucceeds()); 116 } 117 118 TEST_F(MkdirTest, MkdirAtEmptyPath) { 119 ASSERT_THAT(mkdir(dirname_.c_str(), 0777), SyscallSucceeds()); 120 auto fd = 121 ASSERT_NO_ERRNO_AND_VALUE(Open(dirname_, O_RDONLY | O_DIRECTORY, 0666)); 122 EXPECT_THAT(mkdirat(fd.get(), "", 0777), SyscallFailsWithErrno(ENOENT)); 123 } 124 125 TEST_F(MkdirTest, TrailingSlash) { 126 ASSERT_THAT(mkdir((dirname_ + "/").c_str(), 0777), SyscallSucceeds()); 127 } 128 129 } // namespace 130 131 } // namespace testing 132 } // namespace gvisor