gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket.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 <sys/socket.h> 16 #include <sys/stat.h> 17 #include <sys/statfs.h> 18 #include <sys/types.h> 19 #include <sys/wait.h> 20 #include <unistd.h> 21 22 #include "gtest/gtest.h" 23 #include "test/util/file_descriptor.h" 24 #include "test/util/socket_util.h" 25 #include "test/util/temp_umask.h" 26 #include "test/util/test_util.h" 27 28 namespace gvisor { 29 namespace testing { 30 31 // From linux/magic.h, but we can't depend on linux headers here. 32 #define SOCKFS_MAGIC 0x534F434B 33 34 TEST(SocketTest, UnixSocketPairProtocol) { 35 int socks[2]; 36 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, socks), 37 SyscallSucceeds()); 38 close(socks[0]); 39 close(socks[1]); 40 } 41 42 TEST(SocketTest, ProtocolUnix) { 43 struct { 44 int domain, type, protocol; 45 } tests[] = { 46 {AF_UNIX, SOCK_STREAM, PF_UNIX}, 47 {AF_UNIX, SOCK_SEQPACKET, PF_UNIX}, 48 {AF_UNIX, SOCK_DGRAM, PF_UNIX}, 49 }; 50 for (size_t i = 0; i < ABSL_ARRAYSIZE(tests); i++) { 51 ASSERT_NO_ERRNO_AND_VALUE( 52 Socket(tests[i].domain, tests[i].type, tests[i].protocol)); 53 } 54 } 55 56 TEST(SocketTest, ProtocolInet) { 57 struct { 58 int domain, type, protocol; 59 } tests[] = { 60 {AF_INET, SOCK_DGRAM, IPPROTO_UDP}, 61 {AF_INET, SOCK_STREAM, IPPROTO_TCP}, 62 }; 63 for (size_t i = 0; i < ABSL_ARRAYSIZE(tests); i++) { 64 ASSERT_NO_ERRNO_AND_VALUE( 65 Socket(tests[i].domain, tests[i].type, tests[i].protocol)); 66 } 67 } 68 69 TEST(SocketTest, UnixSocketStat) { 70 FileDescriptor bound = 71 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, PF_UNIX)); 72 73 // The permissions of the file created with bind(2) should be defined by the 74 // permissions of the bound socket and the umask. 75 mode_t sock_perm = 0765, mask = 0123; 76 ASSERT_THAT(fchmod(bound.get(), sock_perm), SyscallSucceeds()); 77 TempUmask m(mask); 78 79 struct sockaddr_un addr = 80 ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(/*abstract=*/false, AF_UNIX)); 81 ASSERT_THAT(bind(bound.get(), reinterpret_cast<struct sockaddr*>(&addr), 82 sizeof(addr)), 83 SyscallSucceeds()); 84 85 struct stat statbuf = {}; 86 ASSERT_THAT(stat(addr.sun_path, &statbuf), SyscallSucceeds()); 87 88 // Mode should be S_IFSOCK. 89 EXPECT_EQ(statbuf.st_mode, S_IFSOCK | (sock_perm & ~mask)); 90 91 // Timestamps should be equal and non-zero. 92 EXPECT_NE(statbuf.st_atime, 0); 93 EXPECT_EQ(statbuf.st_atime, statbuf.st_mtime); 94 EXPECT_EQ(statbuf.st_atime, statbuf.st_ctime); 95 } 96 97 TEST(SocketTest, UnixSocketStatFS) { 98 FileDescriptor bound = 99 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, PF_UNIX)); 100 101 struct statfs st; 102 EXPECT_THAT(fstatfs(bound.get(), &st), SyscallSucceeds()); 103 EXPECT_EQ(st.f_type, SOCKFS_MAGIC); 104 EXPECT_EQ(st.f_bsize, getpagesize()); 105 EXPECT_EQ(st.f_namelen, NAME_MAX); 106 } 107 108 TEST(SocketTest, UnixSCMRightsOnlyPassedOnce) { 109 const DisableSave ds; 110 111 int sockets[2]; 112 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 113 // Send more than what will fit inside the send/receive buffers, so that it is 114 // split into multiple messages. 115 constexpr int kBufSize = 0x100000; 116 // Heap allocation is async-signal-unsafe and thus cannot occur between fork() 117 // and execve(). 118 std::vector<char> buf(kBufSize); 119 120 pid_t pid = fork(); 121 if (pid == 0) { 122 TEST_PCHECK(close(sockets[0]) == 0); 123 124 // Construct a message with some control message. 125 struct msghdr msg = {}; 126 char control[CMSG_SPACE(sizeof(int))] = {}; 127 struct iovec iov = {}; 128 msg.msg_control = control; 129 msg.msg_controllen = sizeof(control); 130 131 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); 132 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 133 cmsg->cmsg_level = SOL_SOCKET; 134 cmsg->cmsg_type = SCM_RIGHTS; 135 ((int*)CMSG_DATA(cmsg))[0] = sockets[1]; 136 137 iov.iov_base = buf.data(); 138 iov.iov_len = kBufSize; 139 msg.msg_iov = &iov; 140 msg.msg_iovlen = 1; 141 142 int n = sendmsg(sockets[1], &msg, 0); 143 TEST_PCHECK(n == kBufSize); 144 TEST_PCHECK(shutdown(sockets[1], SHUT_RDWR) == 0); 145 TEST_PCHECK(close(sockets[1]) == 0); 146 _exit(0); 147 } 148 149 close(sockets[1]); 150 151 struct msghdr msg = {}; 152 char control[CMSG_SPACE(sizeof(int))] = {}; 153 struct iovec iov = {}; 154 msg.msg_control = &control; 155 msg.msg_controllen = sizeof(control); 156 157 iov.iov_base = buf.data(); 158 iov.iov_len = kBufSize; 159 msg.msg_iov = &iov; 160 msg.msg_iovlen = 1; 161 162 // The control message should only be present in the first message received. 163 int n; 164 ASSERT_THAT(n = recvmsg(sockets[0], &msg, 0), SyscallSucceeds()); 165 ASSERT_GT(n, 0); 166 ASSERT_EQ(msg.msg_controllen, CMSG_SPACE(sizeof(int))); 167 168 while (n > 0) { 169 ASSERT_THAT(n = recvmsg(sockets[0], &msg, 0), SyscallSucceeds()); 170 ASSERT_EQ(msg.msg_controllen, 0); 171 } 172 173 close(sockets[0]); 174 175 int status; 176 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 177 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 178 } 179 180 TEST(SocketTest, Permission) { 181 FileDescriptor socket = 182 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_DGRAM, 0)); 183 184 auto stat = ASSERT_NO_ERRNO_AND_VALUE(Fstat(socket.get())); 185 EXPECT_EQ(0777, stat.st_mode & ~S_IFMT); 186 } 187 188 using SocketOpenTest = ::testing::TestWithParam<int>; 189 190 // UDS cannot be opened. 191 TEST_P(SocketOpenTest, Unix) { 192 FileDescriptor bound = 193 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, PF_UNIX)); 194 195 struct sockaddr_un addr = 196 ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(/*abstract=*/false, AF_UNIX)); 197 198 ASSERT_THAT(bind(bound.get(), reinterpret_cast<struct sockaddr*>(&addr), 199 sizeof(addr)), 200 SyscallSucceeds()); 201 202 EXPECT_THAT(open(addr.sun_path, GetParam()), SyscallFailsWithErrno(ENXIO)); 203 } 204 205 INSTANTIATE_TEST_SUITE_P(OpenModes, SocketOpenTest, 206 ::testing::Values(O_RDONLY, O_RDWR)); 207 208 } // namespace testing 209 } // namespace gvisor