gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/mknod.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 <sys/socket.h> 18 #include <sys/stat.h> 19 #include <sys/types.h> 20 #include <sys/un.h> 21 #include <unistd.h> 22 23 #include <vector> 24 25 #include "gtest/gtest.h" 26 #include "test/util/file_descriptor.h" 27 #include "test/util/temp_path.h" 28 #include "test/util/test_util.h" 29 #include "test/util/thread_util.h" 30 31 namespace gvisor { 32 namespace testing { 33 34 namespace { 35 36 TEST(MknodTest, RegularFile) { 37 const std::string node0 = NewTempAbsPath(); 38 EXPECT_THAT(mknod(node0.c_str(), S_IFREG, 0), SyscallSucceeds()); 39 40 const std::string node1 = NewTempAbsPath(); 41 EXPECT_THAT(mknod(node1.c_str(), 0, 0), SyscallSucceeds()); 42 } 43 44 TEST(MknodTest, RegularFilePermissions) { 45 const std::string node = NewTempAbsPath(); 46 mode_t newUmask = 0077; 47 umask(newUmask); 48 49 // Attempt to open file with mode 0777. Not specifying file type should create 50 // a regualar file. 51 mode_t perms = S_IRWXU | S_IRWXG | S_IRWXO; 52 EXPECT_THAT(mknod(node.c_str(), perms, 0), SyscallSucceeds()); 53 54 // In the absence of a default ACL, the permissions of the created node are 55 // (mode & ~umask). -- mknod(2) 56 mode_t wantPerms = perms & ~newUmask; 57 struct stat st; 58 ASSERT_THAT(stat(node.c_str(), &st), SyscallSucceeds()); 59 ASSERT_EQ(st.st_mode & 0777, wantPerms); 60 61 // "Zero file type is equivalent to type S_IFREG." - mknod(2) 62 ASSERT_EQ(st.st_mode & S_IFMT, S_IFREG); 63 } 64 65 TEST(MknodTest, MknodAtFIFO) { 66 const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 67 const std::string fifo_relpath = NewTempRelPath(); 68 const std::string fifo = JoinPath(dir.path(), fifo_relpath); 69 70 const FileDescriptor dirfd = 71 ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path().c_str(), O_RDONLY)); 72 ASSERT_THAT(mknodat(dirfd.get(), fifo_relpath.c_str(), S_IFIFO | S_IRUSR, 0), 73 SyscallSucceeds()); 74 75 struct stat st; 76 ASSERT_THAT(stat(fifo.c_str(), &st), SyscallSucceeds()); 77 EXPECT_TRUE(S_ISFIFO(st.st_mode)); 78 } 79 80 TEST(MknodTest, MknodOnExistingPathFails) { 81 const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 82 const TempPath slink = ASSERT_NO_ERRNO_AND_VALUE( 83 TempPath::CreateSymlinkTo(GetAbsoluteTestTmpdir(), file.path())); 84 85 EXPECT_THAT(mknod(file.path().c_str(), S_IFREG, 0), 86 SyscallFailsWithErrno(EEXIST)); 87 EXPECT_THAT(mknod(file.path().c_str(), S_IFIFO, 0), 88 SyscallFailsWithErrno(EEXIST)); 89 EXPECT_THAT(mknod(slink.path().c_str(), S_IFREG, 0), 90 SyscallFailsWithErrno(EEXIST)); 91 EXPECT_THAT(mknod(slink.path().c_str(), S_IFIFO, 0), 92 SyscallFailsWithErrno(EEXIST)); 93 } 94 95 TEST(MknodTest, Socket) { 96 ASSERT_THAT(chdir(GetAbsoluteTestTmpdir().c_str()), SyscallSucceeds()); 97 98 auto filename = NewTempRelPath(); 99 100 ASSERT_THAT(mknod(filename.c_str(), S_IFSOCK | S_IRUSR | S_IWUSR, 0), 101 SyscallSucceeds()); 102 103 int sk; 104 ASSERT_THAT(sk = socket(AF_UNIX, SOCK_SEQPACKET, 0), SyscallSucceeds()); 105 FileDescriptor fd(sk); 106 107 struct sockaddr_un addr = {.sun_family = AF_UNIX}; 108 absl::SNPrintF(addr.sun_path, sizeof(addr.sun_path), "%s", filename.c_str()); 109 ASSERT_THAT(connect(sk, (struct sockaddr *)&addr, sizeof(addr)), 110 SyscallFailsWithErrno(ECONNREFUSED)); 111 ASSERT_THAT(unlink(filename.c_str()), SyscallSucceeds()); 112 } 113 114 TEST(MknodTest, MknodAtEmptyPath) { 115 auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 116 auto fd = 117 ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY | O_DIRECTORY, 0666)); 118 EXPECT_THAT(mknodat(fd.get(), "", S_IFREG | 0777, 0), 119 SyscallFailsWithErrno(ENOENT)); 120 } 121 122 } // namespace 123 124 } // namespace testing 125 } // namespace gvisor