github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/socket_ip_unbound.cc (about)

     1  // Copyright 2019 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 <arpa/inet.h>
    16  #include <netinet/in.h>
    17  #include <sys/socket.h>
    18  #include <sys/types.h>
    19  #include <sys/un.h>
    20  
    21  #include <cstdio>
    22  #include <cstring>
    23  
    24  #include "gmock/gmock.h"
    25  #include "gtest/gtest.h"
    26  #include "test/syscalls/linux/ip_socket_test_util.h"
    27  #include "test/syscalls/linux/socket_test_util.h"
    28  #include "test/util/test_util.h"
    29  
    30  namespace gvisor {
    31  namespace testing {
    32  
    33  // Test fixture for tests that apply to pairs of IP sockets.
    34  using IPUnboundSocketTest = SimpleSocketTest;
    35  
    36  TEST_P(IPUnboundSocketTest, TtlDefault) {
    37    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    38  
    39    int get = -1;
    40    socklen_t get_sz = sizeof(get);
    41    EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get, &get_sz),
    42                SyscallSucceedsWithValue(0));
    43    EXPECT_TRUE(get == 64 || get == 127);
    44    EXPECT_EQ(get_sz, sizeof(get));
    45  }
    46  
    47  TEST_P(IPUnboundSocketTest, SetTtl) {
    48    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    49  
    50    int get1 = -1;
    51    socklen_t get1_sz = sizeof(get1);
    52    EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get1, &get1_sz),
    53                SyscallSucceedsWithValue(0));
    54    EXPECT_EQ(get1_sz, sizeof(get1));
    55  
    56    int set = 100;
    57    if (set == get1) {
    58      set += 1;
    59    }
    60    socklen_t set_sz = sizeof(set);
    61    EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz),
    62                SyscallSucceedsWithValue(0));
    63  
    64    int get2 = -1;
    65    socklen_t get2_sz = sizeof(get2);
    66    EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get2, &get2_sz),
    67                SyscallSucceedsWithValue(0));
    68    EXPECT_EQ(get2_sz, sizeof(get2));
    69    EXPECT_EQ(get2, set);
    70  }
    71  
    72  TEST_P(IPUnboundSocketTest, ResetTtlToDefault) {
    73    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
    74  
    75    int get1 = -1;
    76    socklen_t get1_sz = sizeof(get1);
    77    EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get1, &get1_sz),
    78                SyscallSucceedsWithValue(0));
    79    EXPECT_EQ(get1_sz, sizeof(get1));
    80  
    81    int set1 = 100;
    82    if (set1 == get1) {
    83      set1 += 1;
    84    }
    85    socklen_t set1_sz = sizeof(set1);
    86    EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set1, set1_sz),
    87                SyscallSucceedsWithValue(0));
    88  
    89    int set2 = -1;
    90    socklen_t set2_sz = sizeof(set2);
    91    EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set2, set2_sz),
    92                SyscallSucceedsWithValue(0));
    93  
    94    int get2 = -1;
    95    socklen_t get2_sz = sizeof(get2);
    96    EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get2, &get2_sz),
    97                SyscallSucceedsWithValue(0));
    98    EXPECT_EQ(get2_sz, sizeof(get2));
    99    EXPECT_EQ(get2, get1);
   100  }
   101  
   102  TEST_P(IPUnboundSocketTest, ZeroTtl) {
   103    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   104  
   105    int set = 0;
   106    socklen_t set_sz = sizeof(set);
   107    EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz),
   108                SyscallFailsWithErrno(EINVAL));
   109  }
   110  
   111  TEST_P(IPUnboundSocketTest, InvalidLargeTtl) {
   112    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   113  
   114    int set = 256;
   115    socklen_t set_sz = sizeof(set);
   116    EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz),
   117                SyscallFailsWithErrno(EINVAL));
   118  }
   119  
   120  TEST_P(IPUnboundSocketTest, InvalidNegativeTtl) {
   121    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   122  
   123    int set = -2;
   124    socklen_t set_sz = sizeof(set);
   125    EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz),
   126                SyscallFailsWithErrno(EINVAL));
   127  }
   128  
   129  struct TOSOption {
   130    int level;
   131    int option;
   132    int cmsg_level;
   133  };
   134  
   135  constexpr int INET_ECN_MASK = 3;
   136  
   137  static TOSOption GetTOSOption(int domain) {
   138    TOSOption opt;
   139    switch (domain) {
   140      case AF_INET:
   141        opt.level = IPPROTO_IP;
   142        opt.option = IP_TOS;
   143        opt.cmsg_level = SOL_IP;
   144        break;
   145      case AF_INET6:
   146        opt.level = IPPROTO_IPV6;
   147        opt.option = IPV6_TCLASS;
   148        opt.cmsg_level = SOL_IPV6;
   149        break;
   150    }
   151    return opt;
   152  }
   153  
   154  TEST_P(IPUnboundSocketTest, TOSDefault) {
   155    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   156    TOSOption t = GetTOSOption(GetParam().domain);
   157    int get = -1;
   158    socklen_t get_sz = sizeof(get);
   159    constexpr int kDefaultTOS = 0;
   160    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   161                SyscallSucceedsWithValue(0));
   162    EXPECT_EQ(get_sz, sizeof(get));
   163    EXPECT_EQ(get, kDefaultTOS);
   164  }
   165  
   166  TEST_P(IPUnboundSocketTest, SetTOS) {
   167    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   168    int set = 0xC0;
   169    socklen_t set_sz = sizeof(set);
   170    TOSOption t = GetTOSOption(GetParam().domain);
   171    EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   172                SyscallSucceedsWithValue(0));
   173  
   174    int get = -1;
   175    socklen_t get_sz = sizeof(get);
   176    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   177                SyscallSucceedsWithValue(0));
   178    EXPECT_EQ(get_sz, sizeof(get));
   179    EXPECT_EQ(get, set);
   180  }
   181  
   182  TEST_P(IPUnboundSocketTest, ZeroTOS) {
   183    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   184    int set = 0;
   185    socklen_t set_sz = sizeof(set);
   186    TOSOption t = GetTOSOption(GetParam().domain);
   187    EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   188                SyscallSucceedsWithValue(0));
   189    int get = -1;
   190    socklen_t get_sz = sizeof(get);
   191    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   192                SyscallSucceedsWithValue(0));
   193    EXPECT_EQ(get_sz, sizeof(get));
   194    EXPECT_EQ(get, set);
   195  }
   196  
   197  TEST_P(IPUnboundSocketTest, InvalidLargeTOS) {
   198    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   199    // Test with exceeding the byte space.
   200    int set = 256;
   201    constexpr int kDefaultTOS = 0;
   202    socklen_t set_sz = sizeof(set);
   203    TOSOption t = GetTOSOption(GetParam().domain);
   204    if (GetParam().domain == AF_INET) {
   205      EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   206                  SyscallSucceedsWithValue(0));
   207    } else {
   208      EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   209                  SyscallFailsWithErrno(EINVAL));
   210    }
   211    int get = -1;
   212    socklen_t get_sz = sizeof(get);
   213    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   214                SyscallSucceedsWithValue(0));
   215    EXPECT_EQ(get_sz, sizeof(get));
   216    EXPECT_EQ(get, kDefaultTOS);
   217  }
   218  
   219  TEST_P(IPUnboundSocketTest, CheckSkipECN) {
   220    // Test is inconsistant on different kernels.
   221    SKIP_IF(!IsRunningOnGvisor());
   222    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   223    int set = 0xFF;
   224    socklen_t set_sz = sizeof(set);
   225    TOSOption t = GetTOSOption(GetParam().domain);
   226    EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   227                SyscallSucceedsWithValue(0));
   228    int expect = static_cast<uint8_t>(set);
   229    if (GetParam().protocol == IPPROTO_TCP) {
   230      expect &= ~INET_ECN_MASK;
   231    }
   232    int get = -1;
   233    socklen_t get_sz = sizeof(get);
   234    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   235                SyscallSucceedsWithValue(0));
   236    EXPECT_EQ(get_sz, sizeof(get));
   237    EXPECT_EQ(get, expect);
   238  }
   239  
   240  TEST_P(IPUnboundSocketTest, ZeroTOSOptionSize) {
   241    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   242    int set = 0xC0;
   243    socklen_t set_sz = 0;
   244    TOSOption t = GetTOSOption(GetParam().domain);
   245    if (GetParam().domain == AF_INET) {
   246      EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   247                  SyscallSucceedsWithValue(0));
   248    } else {
   249      EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   250                  SyscallFailsWithErrno(EINVAL));
   251    }
   252    int get = -1;
   253    socklen_t get_sz = 0;
   254    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   255                SyscallSucceedsWithValue(0));
   256    EXPECT_EQ(get_sz, 0);
   257    EXPECT_EQ(get, -1);
   258  }
   259  
   260  TEST_P(IPUnboundSocketTest, SmallTOSOptionSize) {
   261    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   262    int set = 0xC0;
   263    constexpr int kDefaultTOS = 0;
   264    TOSOption t = GetTOSOption(GetParam().domain);
   265    for (socklen_t i = 1; i < sizeof(int); i++) {
   266      int expect_tos;
   267      socklen_t expect_sz;
   268      if (GetParam().domain == AF_INET) {
   269        EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i),
   270                    SyscallSucceedsWithValue(0));
   271        expect_tos = set;
   272        expect_sz = sizeof(uint8_t);
   273      } else {
   274        EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i),
   275                    SyscallFailsWithErrno(EINVAL));
   276        expect_tos = kDefaultTOS;
   277        expect_sz = i;
   278      }
   279      uint get = -1;
   280      socklen_t get_sz = i;
   281      ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   282                  SyscallSucceedsWithValue(0));
   283      EXPECT_EQ(get_sz, expect_sz);
   284      // Account for partial copies by getsockopt, retrieve the lower
   285      // bits specified by get_sz, while comparing against expect_tos.
   286      EXPECT_EQ(get & ~(~0 << (get_sz * 8)), expect_tos);
   287    }
   288  }
   289  
   290  TEST_P(IPUnboundSocketTest, LargeTOSOptionSize) {
   291    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   292    int set = 0xC0;
   293    TOSOption t = GetTOSOption(GetParam().domain);
   294    for (socklen_t i = sizeof(int); i < 10; i++) {
   295      EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i),
   296                  SyscallSucceedsWithValue(0));
   297      int get = -1;
   298      socklen_t get_sz = i;
   299      // We expect the system call handler to only copy atmost sizeof(int) bytes
   300      // as asserted by the check below. Hence, we do not expect the copy to
   301      // overflow in getsockopt.
   302      ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   303                  SyscallSucceedsWithValue(0));
   304      EXPECT_EQ(get_sz, sizeof(int));
   305      EXPECT_EQ(get, set);
   306    }
   307  }
   308  
   309  TEST_P(IPUnboundSocketTest, NegativeTOS) {
   310    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   311  
   312    int set = -1;
   313    socklen_t set_sz = sizeof(set);
   314    TOSOption t = GetTOSOption(GetParam().domain);
   315    EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   316                SyscallSucceedsWithValue(0));
   317    int expect;
   318    if (GetParam().domain == AF_INET) {
   319      expect = static_cast<uint8_t>(set);
   320      if (GetParam().protocol == IPPROTO_TCP) {
   321        expect &= ~INET_ECN_MASK;
   322      }
   323    } else {
   324      // On IPv6 TCLASS, setting -1 has the effect of resetting the
   325      // TrafficClass.
   326      expect = 0;
   327    }
   328    int get = -1;
   329    socklen_t get_sz = sizeof(get);
   330    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   331                SyscallSucceedsWithValue(0));
   332    EXPECT_EQ(get_sz, sizeof(get));
   333    EXPECT_EQ(get, expect);
   334  }
   335  
   336  TEST_P(IPUnboundSocketTest, InvalidNegativeTOS) {
   337    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   338    int set = -2;
   339    socklen_t set_sz = sizeof(set);
   340    TOSOption t = GetTOSOption(GetParam().domain);
   341    int expect;
   342    if (GetParam().domain == AF_INET) {
   343      ASSERT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   344                  SyscallSucceedsWithValue(0));
   345      expect = static_cast<uint8_t>(set);
   346      if (GetParam().protocol == IPPROTO_TCP) {
   347        expect &= ~INET_ECN_MASK;
   348      }
   349    } else {
   350      ASSERT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz),
   351                  SyscallFailsWithErrno(EINVAL));
   352      expect = 0;
   353    }
   354    int get = 0;
   355    socklen_t get_sz = sizeof(get);
   356    ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz),
   357                SyscallSucceedsWithValue(0));
   358    EXPECT_EQ(get_sz, sizeof(get));
   359    EXPECT_EQ(get, expect);
   360  }
   361  
   362  TEST_P(IPUnboundSocketTest, NullTOS) {
   363    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   364    TOSOption t = GetTOSOption(GetParam().domain);
   365    int set_sz = sizeof(int);
   366    if (GetParam().domain == AF_INET) {
   367      EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, nullptr, set_sz),
   368                  SyscallFailsWithErrno(EFAULT));
   369    } else {  // AF_INET6
   370      // The AF_INET6 behavior is not yet compatible. gVisor will try to read
   371      // optval from user memory at syscall handler, it needs substantial
   372      // refactoring to implement this behavior just for IPv6.
   373      if (IsRunningOnGvisor()) {
   374        EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, nullptr, set_sz),
   375                    SyscallFailsWithErrno(EFAULT));
   376      } else {
   377        // Linux's IPv6 stack treats nullptr optval as input of 0, so the call
   378        // succeeds. (net/ipv6/ipv6_sockglue.c, do_ipv6_setsockopt())
   379        //
   380        // Linux's implementation would need fixing as passing a nullptr as optval
   381        // and non-zero optlen may not be valid.
   382        // TODO(b/158666797): Combine the gVisor and linux cases for IPv6.
   383        // Some kernel versions return EFAULT, so we handle both.
   384        EXPECT_THAT(
   385            setsockopt(socket->get(), t.level, t.option, nullptr, set_sz),
   386            AnyOf(SyscallFailsWithErrno(EFAULT), SyscallSucceedsWithValue(0)));
   387      }
   388    }
   389    socklen_t get_sz = sizeof(int);
   390    EXPECT_THAT(getsockopt(socket->get(), t.level, t.option, nullptr, &get_sz),
   391                SyscallFailsWithErrno(EFAULT));
   392    int get = -1;
   393    EXPECT_THAT(getsockopt(socket->get(), t.level, t.option, &get, nullptr),
   394                SyscallFailsWithErrno(EFAULT));
   395  }
   396  
   397  TEST_P(IPUnboundSocketTest, InsufficientBufferTOS) {
   398    SKIP_IF(GetParam().protocol == IPPROTO_TCP);
   399  
   400    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   401    TOSOption t = GetTOSOption(GetParam().domain);
   402  
   403    in_addr addr4;
   404    in6_addr addr6;
   405    ASSERT_THAT(inet_pton(AF_INET, "127.0.0.1", &addr4), ::testing::Eq(1));
   406    ASSERT_THAT(inet_pton(AF_INET6, "fe80::", &addr6), ::testing::Eq(1));
   407  
   408    cmsghdr cmsg = {};
   409    cmsg.cmsg_len = sizeof(cmsg);
   410    cmsg.cmsg_level = t.cmsg_level;
   411    cmsg.cmsg_type = t.option;
   412  
   413    msghdr msg = {};
   414    msg.msg_control = &cmsg;
   415    msg.msg_controllen = sizeof(cmsg);
   416    if (GetParam().domain == AF_INET) {
   417      msg.msg_name = &addr4;
   418      msg.msg_namelen = sizeof(addr4);
   419    } else {
   420      msg.msg_name = &addr6;
   421      msg.msg_namelen = sizeof(addr6);
   422    }
   423  
   424    EXPECT_THAT(sendmsg(socket->get(), &msg, 0), SyscallFailsWithErrno(EINVAL));
   425  }
   426  
   427  TEST_P(IPUnboundSocketTest, ReuseAddrDefault) {
   428    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   429  
   430    int get = -1;
   431    socklen_t get_sz = sizeof(get);
   432    ASSERT_THAT(
   433        getsockopt(socket->get(), SOL_SOCKET, SO_REUSEADDR, &get, &get_sz),
   434        SyscallSucceedsWithValue(0));
   435    EXPECT_EQ(get, kSockOptOff);
   436    EXPECT_EQ(get_sz, sizeof(get));
   437  }
   438  
   439  TEST_P(IPUnboundSocketTest, SetReuseAddr) {
   440    auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
   441  
   442    ASSERT_THAT(setsockopt(socket->get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn,
   443                           sizeof(kSockOptOn)),
   444                SyscallSucceedsWithValue(0));
   445  
   446    int get = -1;
   447    socklen_t get_sz = sizeof(get);
   448    ASSERT_THAT(
   449        getsockopt(socket->get(), SOL_SOCKET, SO_REUSEADDR, &get, &get_sz),
   450        SyscallSucceedsWithValue(0));
   451    EXPECT_EQ(get, kSockOptOn);
   452    EXPECT_EQ(get_sz, sizeof(get));
   453  }
   454  
   455  INSTANTIATE_TEST_SUITE_P(
   456      IPUnboundSockets, IPUnboundSocketTest,
   457      ::testing::ValuesIn(VecCat<SocketKind>(
   458          ApplyVec<SocketKind>(IPv4UDPUnboundSocket,
   459                               std::vector<int>{0, SOCK_NONBLOCK}),
   460          ApplyVec<SocketKind>(IPv6UDPUnboundSocket,
   461                               std::vector<int>{0, SOCK_NONBLOCK}),
   462          ApplyVec<SocketKind>(IPv4TCPUnboundSocket,
   463                               std::vector{0, SOCK_NONBLOCK}),
   464          ApplyVec<SocketKind>(IPv6TCPUnboundSocket,
   465                               std::vector{0, SOCK_NONBLOCK}))));
   466  
   467  }  // namespace testing
   468  }  // namespace gvisor