github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/syscalls/linux/socket_test_util.h" 24 #include "test/util/file_descriptor.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 SKIP_IF(IsRunningWithVFS1()); 71 72 FileDescriptor bound = 73 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, PF_UNIX)); 74 75 // The permissions of the file created with bind(2) should be defined by the 76 // permissions of the bound socket and the umask. 77 mode_t sock_perm = 0765, mask = 0123; 78 ASSERT_THAT(fchmod(bound.get(), sock_perm), SyscallSucceeds()); 79 TempUmask m(mask); 80 81 struct sockaddr_un addr = 82 ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(/*abstract=*/false, AF_UNIX)); 83 ASSERT_THAT(bind(bound.get(), reinterpret_cast<struct sockaddr*>(&addr), 84 sizeof(addr)), 85 SyscallSucceeds()); 86 87 struct stat statbuf = {}; 88 ASSERT_THAT(stat(addr.sun_path, &statbuf), SyscallSucceeds()); 89 90 // Mode should be S_IFSOCK. 91 EXPECT_EQ(statbuf.st_mode, S_IFSOCK | (sock_perm & ~mask)); 92 93 // Timestamps should be equal and non-zero. 94 if (!IsRunningWithVFS1()) { 95 EXPECT_NE(statbuf.st_atime, 0); 96 EXPECT_EQ(statbuf.st_atime, statbuf.st_mtime); 97 EXPECT_EQ(statbuf.st_atime, statbuf.st_ctime); 98 } 99 } 100 101 TEST(SocketTest, UnixSocketStatFS) { 102 SKIP_IF(IsRunningWithVFS1()); 103 104 FileDescriptor bound = 105 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, PF_UNIX)); 106 107 struct statfs st; 108 EXPECT_THAT(fstatfs(bound.get(), &st), SyscallSucceeds()); 109 EXPECT_EQ(st.f_type, SOCKFS_MAGIC); 110 EXPECT_EQ(st.f_bsize, getpagesize()); 111 EXPECT_EQ(st.f_namelen, NAME_MAX); 112 } 113 114 TEST(SocketTest, UnixSCMRightsOnlyPassedOnce) { 115 const DisableSave ds; 116 117 int sockets[2]; 118 ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); 119 // Send more than what will fit inside the send/receive buffers, so that it is 120 // split into multiple messages. 121 constexpr int kBufSize = 0x100000; 122 123 pid_t pid = fork(); 124 if (pid == 0) { 125 TEST_PCHECK(close(sockets[0]) == 0); 126 127 // Construct a message with some control message. 128 struct msghdr msg = {}; 129 char control[CMSG_SPACE(sizeof(int))] = {}; 130 std::vector<char> buf(kBufSize); 131 struct iovec iov = {}; 132 msg.msg_control = control; 133 msg.msg_controllen = sizeof(control); 134 135 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); 136 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 137 cmsg->cmsg_level = SOL_SOCKET; 138 cmsg->cmsg_type = SCM_RIGHTS; 139 ((int*)CMSG_DATA(cmsg))[0] = sockets[1]; 140 141 iov.iov_base = buf.data(); 142 iov.iov_len = kBufSize; 143 msg.msg_iov = &iov; 144 msg.msg_iovlen = 1; 145 146 int n = sendmsg(sockets[1], &msg, 0); 147 TEST_PCHECK(n == kBufSize); 148 TEST_PCHECK(shutdown(sockets[1], SHUT_RDWR) == 0); 149 TEST_PCHECK(close(sockets[1]) == 0); 150 _exit(0); 151 } 152 153 close(sockets[1]); 154 155 struct msghdr msg = {}; 156 char control[CMSG_SPACE(sizeof(int))] = {}; 157 std::vector<char> buf(kBufSize); 158 struct iovec iov = {}; 159 msg.msg_control = &control; 160 msg.msg_controllen = sizeof(control); 161 162 iov.iov_base = buf.data(); 163 iov.iov_len = kBufSize; 164 msg.msg_iov = &iov; 165 msg.msg_iovlen = 1; 166 167 // The control message should only be present in the first message received. 168 int n; 169 ASSERT_THAT(n = recvmsg(sockets[0], &msg, 0), SyscallSucceeds()); 170 ASSERT_GT(n, 0); 171 ASSERT_EQ(msg.msg_controllen, CMSG_SPACE(sizeof(int))); 172 173 while (n > 0) { 174 ASSERT_THAT(n = recvmsg(sockets[0], &msg, 0), SyscallSucceeds()); 175 ASSERT_EQ(msg.msg_controllen, 0); 176 } 177 178 close(sockets[0]); 179 180 int status; 181 ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); 182 ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); 183 } 184 185 using SocketOpenTest = ::testing::TestWithParam<int>; 186 187 // UDS cannot be opened. 188 TEST_P(SocketOpenTest, Unix) { 189 // FIXME(b/142001530): Open incorrectly succeeds on gVisor. 190 SKIP_IF(IsRunningWithVFS1()); 191 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