github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/ioctl.h>
    21  #include <sys/socket.h>
    22  #include <sys/types.h>
    23  #include <sys/un.h>
    24  
    25  #include <vector>
    26  
    27  #include "gtest/gtest.h"
    28  #include "absl/strings/string_view.h"
    29  #include "test/syscalls/linux/socket_test_util.h"
    30  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    31  #include "test/util/test_util.h"
    32  #include "test/util/thread_util.h"
    33  
    34  // This file contains tests specific to Unix domain sockets. It does not contain
    35  // tests for UDS control messages. Those belong in socket_unix_cmsg.cc.
    36  //
    37  // This file is a generic socket test file. It must be built with another file
    38  // that provides the test types.
    39  
    40  namespace gvisor {
    41  namespace testing {
    42  
    43  namespace {
    44  
    45  TEST_P(UnixSocketPairTest, InvalidGetSockOpt) {
    46    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    47    int opt;
    48    socklen_t optlen = sizeof(opt);
    49    EXPECT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, -1, &opt, &optlen),
    50                SyscallFailsWithErrno(ENOPROTOOPT));
    51  }
    52  
    53  TEST_P(UnixSocketPairTest, BindToBadName) {
    54    auto pair =
    55        ASSERT_NO_ERRNO_AND_VALUE(UnixDomainSocketPair(SOCK_SEQPACKET).Create());
    56  
    57    constexpr char kBadName[] = "/some/path/that/does/not/exist";
    58    sockaddr_un sockaddr;
    59    sockaddr.sun_family = AF_LOCAL;
    60    memcpy(sockaddr.sun_path, kBadName, sizeof(kBadName));
    61  
    62    EXPECT_THAT(
    63        bind(pair->first_fd(), reinterpret_cast<struct sockaddr*>(&sockaddr),
    64             sizeof(sockaddr)),
    65        SyscallFailsWithErrno(ENOENT));
    66  }
    67  
    68  TEST_P(UnixSocketPairTest, BindToBadFamily) {
    69    auto pair =
    70        ASSERT_NO_ERRNO_AND_VALUE(UnixDomainSocketPair(SOCK_SEQPACKET).Create());
    71  
    72    constexpr char kBadName[] = "/some/path/that/does/not/exist";
    73    sockaddr_un sockaddr;
    74    sockaddr.sun_family = AF_INET;
    75    memcpy(sockaddr.sun_path, kBadName, sizeof(kBadName));
    76  
    77    EXPECT_THAT(
    78        bind(pair->first_fd(), reinterpret_cast<struct sockaddr*>(&sockaddr),
    79             sizeof(sockaddr)),
    80        SyscallFailsWithErrno(EINVAL));
    81  }
    82  
    83  TEST_P(UnixSocketPairTest, RecvmmsgTimeoutAfterRecv) {
    84    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    85    char sent_data[10];
    86    RandomizeBuffer(sent_data, sizeof(sent_data));
    87  
    88    char received_data[sizeof(sent_data) * 2];
    89    std::vector<struct mmsghdr> msgs(2);
    90    std::vector<struct iovec> iovs(msgs.size());
    91    const int chunk_size = sizeof(received_data) / msgs.size();
    92    for (size_t i = 0; i < msgs.size(); i++) {
    93      iovs[i].iov_len = chunk_size;
    94      iovs[i].iov_base = &received_data[i * chunk_size];
    95      msgs[i].msg_hdr.msg_iov = &iovs[i];
    96      msgs[i].msg_hdr.msg_iovlen = 1;
    97    }
    98  
    99    ASSERT_THAT(WriteFd(sockets->first_fd(), sent_data, sizeof(sent_data)),
   100                SyscallSucceedsWithValue(sizeof(sent_data)));
   101  
   102    struct timespec timeout = {0, 1};
   103    ASSERT_THAT(RetryEINTR(recvmmsg)(sockets->second_fd(), &msgs[0], msgs.size(),
   104                                     0, &timeout),
   105                SyscallSucceedsWithValue(1));
   106  
   107    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data)));
   108  
   109    EXPECT_EQ(chunk_size, msgs[0].msg_len);
   110  }
   111  
   112  TEST_P(UnixSocketPairTest, TIOCINQSucceeds) {
   113    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   114  
   115    if (IsRunningOnGvisor()) {
   116      // TODO(gvisor.dev/issue/273): Inherited host UDS don't support TIOCINQ.
   117      // Skip the test.
   118      int size = -1;
   119      int ret = ioctl(sockets->first_fd(), TIOCINQ, &size);
   120      SKIP_IF(ret == -1 && errno == ENOTTY);
   121    }
   122  
   123    int size = -1;
   124    EXPECT_THAT(ioctl(sockets->first_fd(), TIOCINQ, &size), SyscallSucceeds());
   125    EXPECT_EQ(size, 0);
   126  
   127    const char some_data[] = "dangerzone";
   128    ASSERT_THAT(
   129        RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0),
   130        SyscallSucceeds());
   131    EXPECT_THAT(ioctl(sockets->first_fd(), TIOCINQ, &size), SyscallSucceeds());
   132    EXPECT_EQ(size, sizeof(some_data));
   133  
   134    // Linux only reports the first message's size, which is wrong. We test for
   135    // the behavior described in the man page.
   136    SKIP_IF(!IsRunningOnGvisor());
   137  
   138    ASSERT_THAT(
   139        RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0),
   140        SyscallSucceeds());
   141    EXPECT_THAT(ioctl(sockets->first_fd(), TIOCINQ, &size), SyscallSucceeds());
   142    EXPECT_EQ(size, sizeof(some_data) * 2);
   143  }
   144  
   145  TEST_P(UnixSocketPairTest, TIOCOUTQSucceeds) {
   146    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   147  
   148    if (IsRunningOnGvisor()) {
   149      // TODO(gvisor.dev/issue/273): Inherited host UDS don't support TIOCOUTQ.
   150      // Skip the test.
   151      int size = -1;
   152      int ret = ioctl(sockets->second_fd(), TIOCOUTQ, &size);
   153      SKIP_IF(ret == -1 && errno == ENOTTY);
   154    }
   155  
   156    int size = -1;
   157    EXPECT_THAT(ioctl(sockets->second_fd(), TIOCOUTQ, &size), SyscallSucceeds());
   158    EXPECT_EQ(size, 0);
   159  
   160    // Linux reports bogus numbers which are related to its internal allocations.
   161    // We test for the behavior described in the man page.
   162    SKIP_IF(!IsRunningOnGvisor());
   163  
   164    const char some_data[] = "dangerzone";
   165    ASSERT_THAT(
   166        RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0),
   167        SyscallSucceeds());
   168    EXPECT_THAT(ioctl(sockets->second_fd(), TIOCOUTQ, &size), SyscallSucceeds());
   169    EXPECT_EQ(size, sizeof(some_data));
   170  
   171    ASSERT_THAT(
   172        RetryEINTR(send)(sockets->second_fd(), &some_data, sizeof(some_data), 0),
   173        SyscallSucceeds());
   174    EXPECT_THAT(ioctl(sockets->second_fd(), TIOCOUTQ, &size), SyscallSucceeds());
   175    EXPECT_EQ(size, sizeof(some_data) * 2);
   176  }
   177  
   178  TEST_P(UnixSocketPairTest, NetdeviceIoctlsSucceed) {
   179    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   180  
   181    // Prepare the request.
   182    struct ifreq ifr;
   183    snprintf(ifr.ifr_name, IFNAMSIZ, "lo");
   184  
   185    // Check that the ioctl either succeeds or fails with ENODEV.
   186    int err = ioctl(sockets->first_fd(), SIOCGIFINDEX, &ifr);
   187    if (err < 0) {
   188      ASSERT_EQ(errno, ENODEV);
   189    }
   190  }
   191  
   192  TEST_P(UnixSocketPairTest, Shutdown) {
   193    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   194  
   195    const std::string data = "abc";
   196    ASSERT_THAT(WriteFd(sockets->first_fd(), data.c_str(), data.size()),
   197                SyscallSucceedsWithValue(data.size()));
   198  
   199    ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_RDWR), SyscallSucceeds());
   200    ASSERT_THAT(shutdown(sockets->second_fd(), SHUT_RDWR), SyscallSucceeds());
   201  
   202    // Shutting down a socket does not clear the buffer.
   203    char buf[3];
   204    ASSERT_THAT(ReadFd(sockets->second_fd(), buf, data.size()),
   205                SyscallSucceedsWithValue(data.size()));
   206    EXPECT_EQ(data, absl::string_view(buf, data.size()));
   207  }
   208  
   209  TEST_P(UnixSocketPairTest, ShutdownRead) {
   210    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   211  
   212    ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_RD), SyscallSucceeds());
   213  
   214    // When the socket is shutdown for read, read behavior varies between
   215    // different socket types. This is covered by the various ReadOneSideClosed
   216    // test cases.
   217  
   218    // ... and the peer cannot write.
   219    const std::string data = "abc";
   220    EXPECT_THAT(WriteFd(sockets->second_fd(), data.c_str(), data.size()),
   221                SyscallFailsWithErrno(EPIPE));
   222  
   223    // ... but the socket can still write.
   224    ASSERT_THAT(WriteFd(sockets->first_fd(), data.c_str(), data.size()),
   225                SyscallSucceedsWithValue(data.size()));
   226  
   227    // ... and the peer can still read.
   228    char buf[3];
   229    EXPECT_THAT(ReadFd(sockets->second_fd(), buf, data.size()),
   230                SyscallSucceedsWithValue(data.size()));
   231    EXPECT_EQ(data, absl::string_view(buf, data.size()));
   232  }
   233  
   234  TEST_P(UnixSocketPairTest, ShutdownWrite) {
   235    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   236  
   237    ASSERT_THAT(shutdown(sockets->first_fd(), SHUT_WR), SyscallSucceeds());
   238  
   239    // When the socket is shutdown for write, it cannot write.
   240    const std::string data = "abc";
   241    EXPECT_THAT(WriteFd(sockets->first_fd(), data.c_str(), data.size()),
   242                SyscallFailsWithErrno(EPIPE));
   243  
   244    // ... and the peer read behavior varies between different socket types. This
   245    // is covered by the various ReadOneSideClosed test cases.
   246  
   247    // ... but the peer can still write.
   248    char buf[3];
   249    ASSERT_THAT(WriteFd(sockets->second_fd(), data.c_str(), data.size()),
   250                SyscallSucceedsWithValue(data.size()));
   251  
   252    // ... and the socket can still read.
   253    EXPECT_THAT(ReadFd(sockets->first_fd(), buf, data.size()),
   254                SyscallSucceedsWithValue(data.size()));
   255    EXPECT_EQ(data, absl::string_view(buf, data.size()));
   256  }
   257  
   258  TEST_P(UnixSocketPairTest, SocketReopenFromProcfs) {
   259    // TODO(gvisor.dev/issue/1624): In VFS1, we return EIO instead of ENXIO (see
   260    // b/122310852). Remove this skip once VFS1 is deleted.
   261    SKIP_IF(IsRunningWithVFS1());
   262    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   263  
   264    // Opening a socket pair via /proc/self/fd/X is a ENXIO.
   265    for (const int fd : {sockets->first_fd(), sockets->second_fd()}) {
   266      ASSERT_THAT(Open(absl::StrCat("/proc/self/fd/", fd), O_WRONLY),
   267                  PosixErrorIs(ENXIO, ::testing::_));
   268    }
   269  }
   270  
   271  }  // namespace
   272  
   273  }  // namespace testing
   274  }  // namespace gvisor