gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_non_stream.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_non_stream.h"
    16  
    17  #include <stdio.h>
    18  #include <sys/socket.h>
    19  #include <sys/un.h>
    20  
    21  #include "gtest/gtest.h"
    22  #include "test/syscalls/linux/ip_socket_test_util.h"
    23  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    24  #include "test/util/socket_util.h"
    25  #include "test/util/test_util.h"
    26  
    27  namespace gvisor {
    28  namespace testing {
    29  
    30  TEST_P(NonStreamSocketPairTest, SendMsgTooLarge) {
    31    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    32  
    33    int sndbuf;
    34    socklen_t length = sizeof(sndbuf);
    35    ASSERT_THAT(
    36        getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &sndbuf, &length),
    37        SyscallSucceeds());
    38  
    39    // Make the call too large to fit in the send buffer.
    40    const int buffer_size = 3 * sndbuf;
    41  
    42    EXPECT_THAT(SendLargeSendMsg(sockets, buffer_size, false /* reader */),
    43                SyscallFailsWithErrno(EMSGSIZE));
    44  }
    45  
    46  // Stream sockets allow data sent with a single (e.g. write, sendmsg) syscall
    47  // to be read in pieces with multiple (e.g. read, recvmsg) syscalls.
    48  //
    49  // SplitRecv checks that control messages can only be read on the first (e.g.
    50  // read, recvmsg) syscall, even if it doesn't provide space for the control
    51  // message.
    52  TEST_P(NonStreamSocketPairTest, SplitRecv) {
    53    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    54    char sent_data[512];
    55    RandomizeBuffer(sent_data, sizeof(sent_data));
    56    ASSERT_THAT(
    57        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
    58        SyscallSucceedsWithValue(sizeof(sent_data)));
    59    char received_data[sizeof(sent_data) / 2];
    60    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
    61                                 sizeof(received_data), 0),
    62                SyscallSucceedsWithValue(sizeof(received_data)));
    63    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(received_data)));
    64    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
    65                                 sizeof(received_data), MSG_DONTWAIT),
    66                SyscallFailsWithErrno(EWOULDBLOCK));
    67  }
    68  
    69  // Stream sockets allow data sent with multiple sends to be read in a single
    70  // recv. Datagram sockets do not.
    71  //
    72  // SingleRecv checks that only a single message is readable in a single recv.
    73  TEST_P(NonStreamSocketPairTest, SingleRecv) {
    74    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    75    char sent_data1[20];
    76    RandomizeBuffer(sent_data1, sizeof(sent_data1));
    77    ASSERT_THAT(
    78        RetryEINTR(send)(sockets->first_fd(), sent_data1, sizeof(sent_data1), 0),
    79        SyscallSucceedsWithValue(sizeof(sent_data1)));
    80    char sent_data2[20];
    81    RandomizeBuffer(sent_data2, sizeof(sent_data2));
    82    ASSERT_THAT(
    83        RetryEINTR(send)(sockets->first_fd(), sent_data2, sizeof(sent_data2), 0),
    84        SyscallSucceedsWithValue(sizeof(sent_data2)));
    85    char received_data[sizeof(sent_data1) + sizeof(sent_data2)];
    86    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
    87                                 sizeof(received_data), 0),
    88                SyscallSucceedsWithValue(sizeof(sent_data1)));
    89    EXPECT_EQ(0, memcmp(sent_data1, received_data, sizeof(sent_data1)));
    90  }
    91  
    92  TEST_P(NonStreamSocketPairTest, RecvmsgMsghdrFlagMsgTrunc) {
    93    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    94  
    95    char sent_data[10];
    96    RandomizeBuffer(sent_data, sizeof(sent_data));
    97    ASSERT_THAT(
    98        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
    99        SyscallSucceedsWithValue(sizeof(sent_data)));
   100  
   101    char received_data[sizeof(sent_data) / 2] = {};
   102  
   103    struct iovec iov;
   104    iov.iov_base = received_data;
   105    iov.iov_len = sizeof(received_data);
   106    struct msghdr msg = {};
   107    msg.msg_flags = -1;
   108    msg.msg_iov = &iov;
   109    msg.msg_iovlen = 1;
   110  
   111    ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &msg, 0),
   112                SyscallSucceedsWithValue(sizeof(received_data)));
   113    EXPECT_EQ(0, memcmp(received_data, sent_data, sizeof(received_data)));
   114  
   115    // Check that msghdr flags were updated.
   116    EXPECT_EQ(msg.msg_flags & MSG_TRUNC, MSG_TRUNC);
   117  }
   118  
   119  // Stream sockets allow data sent with multiple sends to be peeked at in a
   120  // single recv. Datagram sockets (except for unix sockets) do not.
   121  //
   122  // SinglePeek checks that only a single message is peekable in a single recv.
   123  TEST_P(NonStreamSocketPairTest, SinglePeek) {
   124    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   125    char sent_data1[20];
   126    RandomizeBuffer(sent_data1, sizeof(sent_data1));
   127    ASSERT_THAT(
   128        RetryEINTR(send)(sockets->first_fd(), sent_data1, sizeof(sent_data1), 0),
   129        SyscallSucceedsWithValue(sizeof(sent_data1)));
   130    char sent_data2[20];
   131    RandomizeBuffer(sent_data2, sizeof(sent_data2));
   132    ASSERT_THAT(
   133        RetryEINTR(send)(sockets->first_fd(), sent_data2, sizeof(sent_data2), 0),
   134        SyscallSucceedsWithValue(sizeof(sent_data2)));
   135    char received_data[sizeof(sent_data1) + sizeof(sent_data2)];
   136    for (int i = 0; i < 3; i++) {
   137      memset(received_data, 0, sizeof(received_data));
   138      ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   139                                   sizeof(received_data), MSG_PEEK),
   140                  SyscallSucceedsWithValue(sizeof(sent_data1)));
   141      EXPECT_EQ(0, memcmp(sent_data1, received_data, sizeof(sent_data1)));
   142    }
   143    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   144                                 sizeof(sent_data1), 0),
   145                SyscallSucceedsWithValue(sizeof(sent_data1)));
   146    EXPECT_EQ(0, memcmp(sent_data1, received_data, sizeof(sent_data1)));
   147    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   148                                 sizeof(sent_data2), 0),
   149                SyscallSucceedsWithValue(sizeof(sent_data2)));
   150    EXPECT_EQ(0, memcmp(sent_data2, received_data, sizeof(sent_data2)));
   151  }
   152  
   153  TEST_P(NonStreamSocketPairTest, MsgTruncTruncation) {
   154    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   155    char sent_data[512];
   156    RandomizeBuffer(sent_data, sizeof(sent_data));
   157    ASSERT_THAT(
   158        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
   159        SyscallSucceedsWithValue(sizeof(sent_data)));
   160    char received_data[sizeof(sent_data)] = {};
   161    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   162                                 sizeof(received_data) / 2, MSG_TRUNC),
   163                SyscallSucceedsWithValue(sizeof(sent_data)));
   164    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data) / 2));
   165  
   166    // Check that we didn't get any extra data.
   167    EXPECT_NE(0, memcmp(sent_data + sizeof(sent_data) / 2,
   168                        received_data + sizeof(received_data) / 2,
   169                        sizeof(sent_data) / 2));
   170  }
   171  
   172  TEST_P(NonStreamSocketPairTest, MsgTruncTruncationRecvmsgMsghdrFlagMsgTrunc) {
   173    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   174  
   175    char sent_data[10];
   176    RandomizeBuffer(sent_data, sizeof(sent_data));
   177    ASSERT_THAT(
   178        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
   179        SyscallSucceedsWithValue(sizeof(sent_data)));
   180  
   181    char received_data[sizeof(sent_data) / 2] = {};
   182  
   183    struct iovec iov;
   184    iov.iov_base = received_data;
   185    iov.iov_len = sizeof(received_data);
   186    struct msghdr msg = {};
   187    msg.msg_flags = -1;
   188    msg.msg_iov = &iov;
   189    msg.msg_iovlen = 1;
   190  
   191    ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &msg, MSG_TRUNC),
   192                SyscallSucceedsWithValue(sizeof(sent_data)));
   193    EXPECT_EQ(0, memcmp(received_data, sent_data, sizeof(received_data)));
   194  
   195    // Check that msghdr flags were updated.
   196    EXPECT_EQ(msg.msg_flags & MSG_TRUNC, MSG_TRUNC);
   197  }
   198  
   199  TEST_P(NonStreamSocketPairTest, MsgTruncSameSize) {
   200    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   201    char sent_data[512];
   202    RandomizeBuffer(sent_data, sizeof(sent_data));
   203    ASSERT_THAT(
   204        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
   205        SyscallSucceedsWithValue(sizeof(sent_data)));
   206    char received_data[sizeof(sent_data)];
   207    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   208                                 sizeof(received_data), MSG_TRUNC),
   209                SyscallSucceedsWithValue(sizeof(received_data)));
   210    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data)));
   211  }
   212  
   213  TEST_P(NonStreamSocketPairTest, MsgTruncNotFull) {
   214    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   215    char sent_data[512];
   216    RandomizeBuffer(sent_data, sizeof(sent_data));
   217    ASSERT_THAT(
   218        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
   219        SyscallSucceedsWithValue(sizeof(sent_data)));
   220    char received_data[2 * sizeof(sent_data)];
   221    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   222                                 sizeof(received_data), MSG_TRUNC),
   223                SyscallSucceedsWithValue(sizeof(sent_data)));
   224    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data)));
   225  }
   226  
   227  // This test tests reading from a socket with MSG_TRUNC and a zero length
   228  // receive buffer. The user should be able to get the message length.
   229  TEST_P(NonStreamSocketPairTest, RecvmsgMsgTruncZeroLen) {
   230    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   231  
   232    char sent_data[10];
   233    RandomizeBuffer(sent_data, sizeof(sent_data));
   234    ASSERT_THAT(
   235        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
   236        SyscallSucceedsWithValue(sizeof(sent_data)));
   237  
   238    // The receive buffer is of zero length.
   239    char received_data[0] = {};
   240  
   241    struct iovec iov;
   242    iov.iov_base = received_data;
   243    iov.iov_len = sizeof(received_data);
   244    struct msghdr msg = {};
   245    msg.msg_flags = -1;
   246    msg.msg_iov = &iov;
   247    msg.msg_iovlen = 1;
   248  
   249    // The syscall succeeds returning the full size of the message on the socket.
   250    ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &msg, MSG_TRUNC),
   251                SyscallSucceedsWithValue(sizeof(sent_data)));
   252  
   253    // Check that MSG_TRUNC is set on msghdr flags.
   254    EXPECT_EQ(msg.msg_flags & MSG_TRUNC, MSG_TRUNC);
   255  }
   256  
   257  // This test tests reading from a socket with MSG_TRUNC | MSG_PEEK and a zero
   258  // length receive buffer. The user should be able to get the message length
   259  // without reading data off the socket.
   260  TEST_P(NonStreamSocketPairTest, RecvmsgMsgTruncMsgPeekZeroLen) {
   261    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   262  
   263    char sent_data[10];
   264    RandomizeBuffer(sent_data, sizeof(sent_data));
   265    ASSERT_THAT(
   266        RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
   267        SyscallSucceedsWithValue(sizeof(sent_data)));
   268  
   269    // The receive buffer is of zero length.
   270    char peek_data[0] = {};
   271  
   272    struct iovec peek_iov;
   273    peek_iov.iov_base = peek_data;
   274    peek_iov.iov_len = sizeof(peek_data);
   275    struct msghdr peek_msg = {};
   276    peek_msg.msg_flags = -1;
   277    peek_msg.msg_iov = &peek_iov;
   278    peek_msg.msg_iovlen = 1;
   279  
   280    // The syscall succeeds returning the full size of the message on the socket.
   281    ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &peek_msg,
   282                                    MSG_TRUNC | MSG_PEEK),
   283                SyscallSucceedsWithValue(sizeof(sent_data)));
   284  
   285    // Check that MSG_TRUNC is set on msghdr flags because the receive buffer is
   286    // smaller than the message size.
   287    EXPECT_EQ(peek_msg.msg_flags & MSG_TRUNC, MSG_TRUNC);
   288  
   289    char received_data[sizeof(sent_data)] = {};
   290  
   291    struct iovec received_iov;
   292    received_iov.iov_base = received_data;
   293    received_iov.iov_len = sizeof(received_data);
   294    struct msghdr received_msg = {};
   295    received_msg.msg_flags = -1;
   296    received_msg.msg_iov = &received_iov;
   297    received_msg.msg_iovlen = 1;
   298  
   299    // Next we can read the actual data.
   300    ASSERT_THAT(
   301        RetryEINTR(recvmsg)(sockets->second_fd(), &received_msg, MSG_TRUNC),
   302        SyscallSucceedsWithValue(sizeof(sent_data)));
   303  
   304    EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data)));
   305  
   306    // Check that MSG_TRUNC is not set on msghdr flags because we read the whole
   307    // message.
   308    EXPECT_EQ(received_msg.msg_flags & MSG_TRUNC, 0);
   309  }
   310  
   311  // This test tests reading from a socket with MSG_TRUNC | MSG_PEEK and a zero
   312  // length receive buffer and MSG_DONTWAIT. The user should be able to get an
   313  // EAGAIN or EWOULDBLOCK error response.
   314  TEST_P(NonStreamSocketPairTest, RecvmsgTruncPeekDontwaitZeroLen) {
   315    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   316  
   317    // NOTE: We don't send any data on the socket.
   318  
   319    // The receive buffer is of zero length.
   320    char peek_data[0] = {};
   321  
   322    struct iovec peek_iov;
   323    peek_iov.iov_base = peek_data;
   324    peek_iov.iov_len = sizeof(peek_data);
   325    struct msghdr peek_msg = {};
   326    peek_msg.msg_flags = -1;
   327    peek_msg.msg_iov = &peek_iov;
   328    peek_msg.msg_iovlen = 1;
   329  
   330    // recvmsg fails with EAGAIN because no data is available on the socket.
   331    ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &peek_msg,
   332                                    MSG_TRUNC | MSG_PEEK | MSG_DONTWAIT),
   333                SyscallFailsWithErrno(EAGAIN));
   334  }
   335  
   336  }  // namespace testing
   337  }  // namespace gvisor