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