gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_unix.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 "test/syscalls/linux/socket_unix.h" 16 17 #include <errno.h> 18 #include <net/if.h> 19 #include <stdio.h> 20 #include <sys/epoll.h> 21 #include <sys/ioctl.h> 22 #include <sys/socket.h> 23 #include <sys/types.h> 24 #include <sys/un.h> 25 26 #include <vector> 27 28 #include "gtest/gtest.h" 29 #include "absl/strings/string_view.h" 30 #include "test/syscalls/linux/unix_domain_socket_test_util.h" 31 #include "test/util/epoll_util.h" 32 #include "test/util/file_descriptor.h" 33 #include "test/util/memory_util.h" 34 #include "test/util/posix_error.h" 35 #include "test/util/save_util.h" 36 #include "test/util/socket_util.h" 37 #include "test/util/temp_path.h" 38 #include "test/util/test_util.h" 39 #include "test/util/thread_util.h" 40 41 // This file contains tests specific to Unix domain sockets. It does not contain 42 // tests for UDS control messages. Those belong in socket_unix_cmsg.cc. 43 // 44 // This file is a generic socket test file. It must be built with another file 45 // that provides the test types. 46 47 namespace gvisor { 48 namespace testing { 49 50 namespace { 51 52 TEST_P(UnixSocketPairTest, InvalidGetSockOpt) { 53 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 54 int opt; 55 socklen_t optlen = sizeof(opt); 56 EXPECT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, -1, &opt, &optlen), 57 SyscallFailsWithErrno(ENOPROTOOPT)); 58 } 59 60 TEST_P(UnixSocketPairTest, BindToBadName) { 61 auto pair = 62 ASSERT_NO_ERRNO_AND_VALUE(UnixDomainSocketPair(SOCK_SEQPACKET).Create()); 63 64 constexpr char kBadName[] = "/some/path/that/does/not/exist"; 65 sockaddr_un sockaddr; 66 sockaddr.sun_family = AF_LOCAL; 67 memcpy(sockaddr.sun_path, kBadName, sizeof(kBadName)); 68 69 EXPECT_THAT( 70 bind(pair->first_fd(), reinterpret_cast<struct sockaddr*>(&sockaddr), 71 sizeof(sockaddr)), 72 SyscallFailsWithErrno(ENOENT)); 73 } 74 75 TEST_P(UnixSocketPairTest, BindToBadFamily) { 76 auto pair = 77 ASSERT_NO_ERRNO_AND_VALUE(UnixDomainSocketPair(SOCK_SEQPACKET).Create()); 78 79 constexpr char kBadName[] = "/some/path/that/does/not/exist"; 80 sockaddr_un sockaddr; 81 sockaddr.sun_family = AF_INET; 82 memcpy(sockaddr.sun_path, kBadName, sizeof(kBadName)); 83 84 EXPECT_THAT( 85 bind(pair->first_fd(), reinterpret_cast<struct sockaddr*>(&sockaddr), 86 sizeof(sockaddr)), 87 SyscallFailsWithErrno(EINVAL)); 88 } 89 90 TEST_P(UnixSocketPairTest, RecvmmsgTimeoutAfterRecv) { 91 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 92 char sent_data[10]; 93 RandomizeBuffer(sent_data, sizeof(sent_data)); 94 95 char received_data[sizeof(sent_data) * 2]; 96 std::vector<struct mmsghdr> msgs(2); 97 std::vector<struct iovec> iovs(msgs.size()); 98 const int chunk_size = sizeof(received_data) / msgs.size(); 99 for (size_t i = 0; i < msgs.size(); i++) { 100 iovs[i].iov_len = chunk_size; 101 iovs[i].iov_base = &received_data[i * chunk_size]; 102 msgs[i].msg_hdr.msg_iov = &iovs[i]; 103 msgs[i].msg_hdr.msg_iovlen = 1; 104 } 105 106 ASSERT_THAT(WriteFd(sockets->first_fd(), sent_data, sizeof(sent_data)), 107 SyscallSucceedsWithValue(sizeof(sent_data))); 108 109 struct timespec timeout = {0, 1}; 110 ASSERT_THAT(RetryEINTR(recvmmsg)(sockets->second_fd(), &msgs[0], msgs.size(), 111 0, &timeout), 112 SyscallSucceedsWithValue(1)); 113 114 EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data))); 115 116 EXPECT_EQ(chunk_size, msgs[0].msg_len); 117 } 118 119 TEST_P(UnixSocketPairTest, TIOCINQSucceeds) { 120 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 121 122 if (IsRunningOnGvisor()) { 123 // TODO(gvisor.dev/issue/273): Inherited host UDS don't support TIOCINQ. 124 // Skip the test. 125 int size = -1; 126 int ret = ioctl(sockets->first_fd(), TIOCINQ, &size); 127 SKIP_IF(ret == -1 && errno == ENOTTY); 128 } 129 130 int size = -1; 131 EXPECT_THAT(ioctl(sockets->first_fd(), TIOCINQ, &size), SyscallSucceeds()); 132 EXPECT_EQ(size, 0); 133 134 const char some_data[] = "dangerzone"; 135 ASSERT_THAT( 136 RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0), 137 SyscallSucceeds()); 138 EXPECT_THAT(ioctl(sockets->first_fd(), TIOCINQ, &size), SyscallSucceeds()); 139 EXPECT_EQ(size, sizeof(some_data)); 140 141 // Linux only reports the first message's size, which is wrong. We test for 142 // the behavior described in the man page. 143 SKIP_IF(!IsRunningOnGvisor()); 144 145 ASSERT_THAT( 146 RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0), 147 SyscallSucceeds()); 148 EXPECT_THAT(ioctl(sockets->first_fd(), TIOCINQ, &size), SyscallSucceeds()); 149 EXPECT_EQ(size, sizeof(some_data) * 2); 150 } 151 152 TEST_P(UnixSocketPairTest, TIOCOUTQSucceeds) { 153 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 154 155 if (IsRunningOnGvisor()) { 156 // TODO(gvisor.dev/issue/273): Inherited host UDS don't support TIOCOUTQ. 157 // Skip the test. 158 int size = -1; 159 int ret = ioctl(sockets->second_fd(), TIOCOUTQ, &size); 160 SKIP_IF(ret == -1 && errno == ENOTTY); 161 } 162 163 int size = -1; 164 EXPECT_THAT(ioctl(sockets->second_fd(), TIOCOUTQ, &size), SyscallSucceeds()); 165 EXPECT_EQ(size, 0); 166 167 // Linux reports bogus numbers which are related to its internal allocations. 168 // We test for the behavior described in the man page. 169 SKIP_IF(!IsRunningOnGvisor()); 170 171 const char some_data[] = "dangerzone"; 172 ASSERT_THAT( 173 RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0), 174 SyscallSucceeds()); 175 EXPECT_THAT(ioctl(sockets->second_fd(), TIOCOUTQ, &size), SyscallSucceeds()); 176 EXPECT_EQ(size, sizeof(some_data)); 177 178 ASSERT_THAT( 179 RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0), 180 SyscallSucceeds()); 181 EXPECT_THAT(ioctl(sockets->second_fd(), TIOCOUTQ, &size), SyscallSucceeds()); 182 EXPECT_EQ(size, sizeof(some_data) * 2); 183 } 184 185 TEST_P(UnixSocketPairTest, NetdeviceIoctlsSucceed) { 186 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 187 188 // Prepare the request. 189 struct ifreq ifr; 190 snprintf(ifr.ifr_name, IFNAMSIZ, "lo"); 191 192 // Check that the ioctl either succeeds or fails with ENODEV. 193 int err = ioctl(sockets->first_fd(), SIOCGIFINDEX, &ifr); 194 if (err < 0) { 195 ASSERT_EQ(errno, ENODEV); 196 } 197 } 198 199 TEST_P(UnixSocketPairTest, Shutdown) { 200 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 201 202 const std::string data = "abc"; 203 ASSERT_THAT(WriteFd(sockets->first_fd(), data.c_str(), data.size()), 204 SyscallSucceedsWithValue(data.size())); 205 206 ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_RDWR), SyscallSucceeds()); 207 ASSERT_THAT(shutdown(sockets->second_fd(), SHUT_RDWR), SyscallSucceeds()); 208 209 // Shutting down a socket does not clear the buffer. 210 char buf[3]; 211 ASSERT_THAT(ReadFd(sockets->second_fd(), buf, data.size()), 212 SyscallSucceedsWithValue(data.size())); 213 EXPECT_EQ(data, absl::string_view(buf, data.size())); 214 } 215 216 TEST_P(UnixSocketPairTest, ShutdownRead) { 217 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 218 219 ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_RD), SyscallSucceeds()); 220 221 // When the socket is shutdown for read, read behavior varies between 222 // different socket types. This is covered by the various ReadOneSideClosed 223 // test cases. 224 225 // ... and the peer cannot write. 226 const std::string data = "abc"; 227 EXPECT_THAT(WriteFd(sockets->second_fd(), data.c_str(), data.size()), 228 SyscallFailsWithErrno(EPIPE)); 229 230 // ... but the socket can still write. 231 ASSERT_THAT(WriteFd(sockets->first_fd(), data.c_str(), data.size()), 232 SyscallSucceedsWithValue(data.size())); 233 234 // ... and the peer can still read. 235 char buf[3]; 236 EXPECT_THAT(ReadFd(sockets->second_fd(), buf, data.size()), 237 SyscallSucceedsWithValue(data.size())); 238 EXPECT_EQ(data, absl::string_view(buf, data.size())); 239 } 240 241 TEST_P(UnixSocketPairTest, ShutdownWrite) { 242 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 243 244 ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_WR), SyscallSucceeds()); 245 246 // When the socket is shutdown for write, it cannot write. 247 const std::string data = "abc"; 248 EXPECT_THAT(WriteFd(sockets->first_fd(), data.c_str(), data.size()), 249 SyscallFailsWithErrno(EPIPE)); 250 251 // ... and the peer read behavior varies between different socket types. This 252 // is covered by the various ReadOneSideClosed test cases. 253 254 // ... but the peer can still write. 255 char buf[3]; 256 ASSERT_THAT(WriteFd(sockets->second_fd(), data.c_str(), data.size()), 257 SyscallSucceedsWithValue(data.size())); 258 259 // ... and the socket can still read. 260 EXPECT_THAT(ReadFd(sockets->first_fd(), buf, data.size()), 261 SyscallSucceedsWithValue(data.size())); 262 EXPECT_EQ(data, absl::string_view(buf, data.size())); 263 } 264 265 TEST_P(UnixSocketPairTest, SocketReopenFromProcfs) { 266 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 267 268 // Opening a socket pair via /proc/self/fd/X is a ENXIO. 269 for (const int fd : {sockets->first_fd(), sockets->second_fd()}) { 270 ASSERT_THAT(Open(absl::StrCat("/proc/self/fd/", fd), O_WRONLY), 271 PosixErrorIs(ENXIO, ::testing::_)); 272 } 273 } 274 275 // Repro for b/196804997. 276 TEST_P(UnixSocketPairTest, SendFromMmapBeyondEof) { 277 TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 278 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY)); 279 Mapping m = ASSERT_NO_ERRNO_AND_VALUE( 280 Mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, fd.get(), 0)); 281 282 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 283 ASSERT_THAT(send(sockets->first_fd(), m.ptr(), m.len(), 0), 284 SyscallFailsWithErrno(EFAULT)); 285 } 286 287 // Repro for b/322538038. 288 TEST_P(UnixSocketPairTest, EpollEdgeTrigger) { 289 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 290 auto epollfd = ASSERT_NO_ERRNO_AND_VALUE(NewEpollFD()); 291 ASSERT_NO_ERRNO(RegisterEpollFD(epollfd.get(), sockets->second_fd(), 292 EPOLLIN | EPOLLET, sockets->second_fd())); 293 294 // Disable save/restore for this test since restoring a file description that 295 // is ready for I/O will re-arm epoll notifications, regardless of EPOLLET. 296 DisableSave ds; 297 298 // Write to the first end of the socketpair and expect the second end to 299 // become readable. 300 char buf = 8; 301 ASSERT_THAT(WriteFd(sockets->first_fd(), &buf, sizeof(buf)), 302 SyscallSucceedsWithValue(sizeof(buf))); 303 struct epoll_event ev; 304 ASSERT_THAT(RetryEINTR(epoll_wait)(epollfd.get(), &ev, 1, 1000 /* timeout */), 305 SyscallSucceedsWithValue(1)); 306 EXPECT_EQ(ev.events, EPOLLIN); 307 EXPECT_EQ(ev.data.u64, sockets->second_fd()); 308 309 // Expect another epoll_wait to return no events since the epoll interest is 310 // edge-triggered (registered with EPOLLET) rather than level-triggered. 311 EXPECT_THAT(RetryEINTR(epoll_wait)(epollfd.get(), &ev, 1, 1000 /* timeout */), 312 SyscallSucceedsWithValue(0)); 313 314 // Write to the first end of the socketpair again and expect a second epoll 315 // notification, despite the second end having remained readable since the 316 // first write. 317 ASSERT_THAT(WriteFd(sockets->first_fd(), &buf, sizeof(buf)), 318 SyscallSucceedsWithValue(sizeof(buf))); 319 ASSERT_THAT(RetryEINTR(epoll_wait)(epollfd.get(), &ev, 1, 1000 /* timeout */), 320 SyscallSucceedsWithValue(1)); 321 EXPECT_EQ(ev.events, EPOLLIN); 322 EXPECT_EQ(ev.data.u64, sockets->second_fd()); 323 } 324 325 } // namespace 326 327 } // namespace testing 328 } // namespace gvisor