github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/socket_netlink.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 <linux/netlink.h>
    16  #include <sys/socket.h>
    17  #include <sys/types.h>
    18  #include <unistd.h>
    19  
    20  #include "gtest/gtest.h"
    21  #include "test/syscalls/linux/socket_test_util.h"
    22  #include "test/util/file_descriptor.h"
    23  #include "test/util/test_util.h"
    24  
    25  // Tests for all netlink socket protocols.
    26  
    27  namespace gvisor {
    28  namespace testing {
    29  
    30  namespace {
    31  
    32  // NetlinkTest parameter is the protocol to test.
    33  using NetlinkTest = ::testing::TestWithParam<int>;
    34  
    35  // Netlink sockets must be SOCK_DGRAM or SOCK_RAW.
    36  TEST_P(NetlinkTest, Types) {
    37    const int protocol = GetParam();
    38  
    39    EXPECT_THAT(socket(AF_NETLINK, SOCK_STREAM, protocol),
    40                SyscallFailsWithErrno(ESOCKTNOSUPPORT));
    41    EXPECT_THAT(socket(AF_NETLINK, SOCK_SEQPACKET, protocol),
    42                SyscallFailsWithErrno(ESOCKTNOSUPPORT));
    43    EXPECT_THAT(socket(AF_NETLINK, SOCK_RDM, protocol),
    44                SyscallFailsWithErrno(ESOCKTNOSUPPORT));
    45    EXPECT_THAT(socket(AF_NETLINK, SOCK_DCCP, protocol),
    46                SyscallFailsWithErrno(ESOCKTNOSUPPORT));
    47    EXPECT_THAT(socket(AF_NETLINK, SOCK_PACKET, protocol),
    48                SyscallFailsWithErrno(ESOCKTNOSUPPORT));
    49  
    50    int fd;
    51    EXPECT_THAT(fd = socket(AF_NETLINK, SOCK_DGRAM, protocol), SyscallSucceeds());
    52    EXPECT_THAT(close(fd), SyscallSucceeds());
    53  
    54    EXPECT_THAT(fd = socket(AF_NETLINK, SOCK_RAW, protocol), SyscallSucceeds());
    55    EXPECT_THAT(close(fd), SyscallSucceeds());
    56  }
    57  
    58  TEST_P(NetlinkTest, AutomaticPort) {
    59    const int protocol = GetParam();
    60  
    61    FileDescriptor fd =
    62        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_NETLINK, SOCK_RAW, protocol));
    63  
    64    struct sockaddr_nl addr = {};
    65    addr.nl_family = AF_NETLINK;
    66  
    67    EXPECT_THAT(
    68        bind(fd.get(), reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)),
    69        SyscallSucceeds());
    70  
    71    socklen_t addrlen = sizeof(addr);
    72    EXPECT_THAT(getsockname(fd.get(), reinterpret_cast<struct sockaddr*>(&addr),
    73                            &addrlen),
    74                SyscallSucceeds());
    75    EXPECT_EQ(addrlen, sizeof(addr));
    76    // This is the only netlink socket in the process, so it should get the PID as
    77    // the port id.
    78    //
    79    // N.B. Another process could theoretically have explicitly reserved our pid
    80    // as a port ID, but that is very unlikely.
    81    EXPECT_EQ(addr.nl_pid, getpid());
    82  }
    83  
    84  // Calling connect automatically binds to an automatic port.
    85  TEST_P(NetlinkTest, ConnectBinds) {
    86    const int protocol = GetParam();
    87  
    88    FileDescriptor fd =
    89        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_NETLINK, SOCK_RAW, protocol));
    90  
    91    struct sockaddr_nl addr = {};
    92    addr.nl_family = AF_NETLINK;
    93  
    94    EXPECT_THAT(connect(fd.get(), reinterpret_cast<struct sockaddr*>(&addr),
    95                        sizeof(addr)),
    96                SyscallSucceeds());
    97  
    98    socklen_t addrlen = sizeof(addr);
    99    EXPECT_THAT(getsockname(fd.get(), reinterpret_cast<struct sockaddr*>(&addr),
   100                            &addrlen),
   101                SyscallSucceeds());
   102    EXPECT_EQ(addrlen, sizeof(addr));
   103  
   104    // Each test is running in a pid namespace, so another process can explicitly
   105    // reserve our pid as a port ID. In this case, a negative portid value will be
   106    // set.
   107    if (static_cast<pid_t>(addr.nl_pid) > 0) {
   108      EXPECT_EQ(addr.nl_pid, getpid());
   109    }
   110  
   111    memset(&addr, 0, sizeof(addr));
   112    addr.nl_family = AF_NETLINK;
   113  
   114    // Connecting again is allowed, but keeps the same port.
   115    EXPECT_THAT(connect(fd.get(), reinterpret_cast<struct sockaddr*>(&addr),
   116                        sizeof(addr)),
   117                SyscallSucceeds());
   118  
   119    addrlen = sizeof(addr);
   120    EXPECT_THAT(getsockname(fd.get(), reinterpret_cast<struct sockaddr*>(&addr),
   121                            &addrlen),
   122                SyscallSucceeds());
   123    EXPECT_EQ(addrlen, sizeof(addr));
   124    EXPECT_EQ(addr.nl_pid, getpid());
   125  }
   126  
   127  TEST_P(NetlinkTest, GetPeerName) {
   128    const int protocol = GetParam();
   129  
   130    FileDescriptor fd =
   131        ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_NETLINK, SOCK_RAW, protocol));
   132  
   133    struct sockaddr_nl addr = {};
   134    socklen_t addrlen = sizeof(addr);
   135  
   136    EXPECT_THAT(getpeername(fd.get(), reinterpret_cast<struct sockaddr*>(&addr),
   137                            &addrlen),
   138                SyscallSucceeds());
   139  
   140    EXPECT_EQ(addrlen, sizeof(addr));
   141    EXPECT_EQ(addr.nl_family, AF_NETLINK);
   142    // Peer is the kernel if we didn't connect elsewhere.
   143    EXPECT_EQ(addr.nl_pid, 0);
   144  }
   145  
   146  INSTANTIATE_TEST_SUITE_P(ProtocolTest, NetlinkTest,
   147                           ::testing::Values(NETLINK_ROUTE,
   148                                             NETLINK_KOBJECT_UEVENT));
   149  
   150  }  // namespace
   151  
   152  }  // namespace testing
   153  }  // namespace gvisor