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