gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_unix_unbound_dgram.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 <stdio.h>
    16  #include <sys/socket.h>
    17  #include <sys/un.h>
    18  
    19  #include "gtest/gtest.h"
    20  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    21  #include "test/util/socket_util.h"
    22  #include "test/util/test_util.h"
    23  
    24  namespace gvisor {
    25  namespace testing {
    26  
    27  namespace {
    28  
    29  // Test fixture for tests that apply to pairs of unbound dgram unix sockets.
    30  using UnboundDgramUnixSocketPairTest = SocketPairTest;
    31  
    32  TEST_P(UnboundDgramUnixSocketPairTest, BindConnect) {
    33    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    34    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
    35                     sockets->first_addr_size()),
    36                SyscallSucceeds());
    37    ASSERT_THAT(connect(sockets->second_fd(), sockets->first_addr(),
    38                        sockets->first_addr_size()),
    39                SyscallSucceeds());
    40  }
    41  
    42  TEST_P(UnboundDgramUnixSocketPairTest, SelfConnect) {
    43    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    44    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
    45                     sockets->first_addr_size()),
    46                SyscallSucceeds());
    47    ASSERT_THAT(connect(sockets->first_fd(), sockets->first_addr(),
    48                        sockets->first_addr_size()),
    49                SyscallSucceeds());
    50  }
    51  
    52  TEST_P(UnboundDgramUnixSocketPairTest, DoubleConnect) {
    53    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    54    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
    55                     sockets->first_addr_size()),
    56                SyscallSucceeds());
    57    ASSERT_THAT(connect(sockets->second_fd(), sockets->first_addr(),
    58                        sockets->first_addr_size()),
    59                SyscallSucceeds());
    60    ASSERT_THAT(connect(sockets->second_fd(), sockets->first_addr(),
    61                        sockets->first_addr_size()),
    62                SyscallSucceeds());
    63  }
    64  
    65  TEST_P(UnboundDgramUnixSocketPairTest, GetRemoteAddress) {
    66    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    67    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
    68                     sockets->first_addr_size()),
    69                SyscallSucceeds());
    70    ASSERT_THAT(connect(sockets->second_fd(), sockets->first_addr(),
    71                        sockets->first_addr_size()),
    72                SyscallSucceeds());
    73  
    74    socklen_t addressLength = sockets->first_addr_size();
    75    struct sockaddr_storage address = {};
    76    ASSERT_THAT(getpeername(sockets->second_fd(), (struct sockaddr*)(&address),
    77                            &addressLength),
    78                SyscallSucceeds());
    79    EXPECT_EQ(
    80        0, memcmp(&address, sockets->first_addr(), sockets->first_addr_size()));
    81  }
    82  
    83  TEST_P(UnboundDgramUnixSocketPairTest, Sendto) {
    84    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    85    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
    86                     sockets->first_addr_size()),
    87                SyscallSucceeds());
    88  
    89    char sent_data[20];
    90    RandomizeBuffer(sent_data, sizeof(sent_data));
    91  
    92    ASSERT_THAT(sendto(sockets->second_fd(), sent_data, sizeof(sent_data), 0,
    93                       sockets->first_addr(), sockets->first_addr_size()),
    94                SyscallSucceedsWithValue(sizeof(sent_data)));
    95  
    96    char received_data[sizeof(sent_data)];
    97    ASSERT_THAT(ReadFd(sockets->first_fd(), received_data, sizeof(received_data)),
    98                SyscallSucceedsWithValue(sizeof(received_data)));
    99    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(received_data)));
   100  }
   101  
   102  TEST_P(UnboundDgramUnixSocketPairTest, ZeroWriteAllowed) {
   103    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   104    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
   105                     sockets->first_addr_size()),
   106                SyscallSucceeds());
   107    ASSERT_THAT(connect(sockets->second_fd(), sockets->first_addr(),
   108                        sockets->first_addr_size()),
   109                SyscallSucceeds());
   110  
   111    char sent_data[3];
   112    // Send a zero length packet.
   113    ASSERT_THAT(write(sockets->second_fd(), sent_data, 0),
   114                SyscallSucceedsWithValue(0));
   115    // Receive the packet.
   116    char received_data[sizeof(sent_data)];
   117    ASSERT_THAT(read(sockets->first_fd(), received_data, sizeof(received_data)),
   118                SyscallSucceedsWithValue(0));
   119  }
   120  
   121  TEST_P(UnboundDgramUnixSocketPairTest, Listen) {
   122    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   123    ASSERT_THAT(listen(sockets->first_fd(), 0), SyscallFailsWithErrno(ENOTSUP));
   124  }
   125  
   126  TEST_P(UnboundDgramUnixSocketPairTest, Accept) {
   127    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   128    ASSERT_THAT(accept(sockets->first_fd(), nullptr, nullptr),
   129                SyscallFailsWithErrno(ENOTSUP));
   130  }
   131  
   132  TEST_P(UnboundDgramUnixSocketPairTest, SendtoWithoutConnect) {
   133    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   134  
   135    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
   136                     sockets->first_addr_size()),
   137                SyscallSucceeds());
   138  
   139    char data = 'a';
   140    ASSERT_THAT(
   141        RetryEINTR(sendto)(sockets->second_fd(), &data, sizeof(data), 0,
   142                           sockets->first_addr(), sockets->first_addr_size()),
   143        SyscallSucceedsWithValue(sizeof(data)));
   144  }
   145  
   146  TEST_P(UnboundDgramUnixSocketPairTest, SendtoWithoutConnectPassCreds) {
   147    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   148  
   149    ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
   150                     sockets->first_addr_size()),
   151                SyscallSucceeds());
   152  
   153    SetSoPassCred(sockets->first_fd());
   154    char data = 'a';
   155    ASSERT_THAT(
   156        RetryEINTR(sendto)(sockets->second_fd(), &data, sizeof(data), 0,
   157                           sockets->first_addr(), sockets->first_addr_size()),
   158        SyscallSucceedsWithValue(sizeof(data)));
   159    ucred creds;
   160    creds.pid = -1;
   161    char buf[sizeof(data) + 1];
   162    ASSERT_NO_FATAL_FAILURE(
   163        RecvCreds(sockets->first_fd(), &creds, buf, sizeof(buf), sizeof(data)));
   164    EXPECT_EQ(0, memcmp(&data, buf, sizeof(data)));
   165    EXPECT_THAT(getpid(), SyscallSucceedsWithValue(creds.pid));
   166  }
   167  
   168  INSTANTIATE_TEST_SUITE_P(
   169      AllUnixDomainSockets, UnboundDgramUnixSocketPairTest,
   170      ::testing::ValuesIn(VecCat<SocketPairKind>(
   171          ApplyVec<SocketPairKind>(FilesystemUnboundUnixDomainSocketPair,
   172                                   AllBitwiseCombinations(List<int>{SOCK_DGRAM},
   173                                                          List<int>{
   174                                                              0, SOCK_NONBLOCK})),
   175          ApplyVec<SocketPairKind>(
   176              AbstractUnboundUnixDomainSocketPair,
   177              AllBitwiseCombinations(List<int>{SOCK_DGRAM},
   178                                     List<int>{0, SOCK_NONBLOCK})))));
   179  
   180  }  // namespace
   181  
   182  }  // namespace testing
   183  }  // namespace gvisor