gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/packet_socket.cc (about) 1 // Copyright 2021 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 <net/if.h> 16 #include <netinet/if_ether.h> 17 #include <netpacket/packet.h> 18 #include <poll.h> 19 #include <sys/socket.h> 20 #include <sys/types.h> 21 22 #include <cerrno> 23 #include <limits> 24 25 #include "gmock/gmock.h" 26 #include "gtest/gtest.h" 27 #include "test/syscalls/linux/ip_socket_test_util.h" 28 #include "test/util/capability_util.h" 29 #include "test/util/file_descriptor.h" 30 #include "test/util/socket_util.h" 31 #include "test/util/test_util.h" 32 33 namespace gvisor { 34 namespace testing { 35 36 namespace { 37 38 using ::testing::AnyOf; 39 using ::testing::Combine; 40 using ::testing::Eq; 41 using ::testing::Values; 42 43 class PacketSocketCreationTest 44 : public ::testing::TestWithParam<std::tuple<int, int>> { 45 protected: 46 void SetUp() override { 47 if (!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())) { 48 const auto [type, protocol] = GetParam(); 49 ASSERT_THAT(socket(AF_PACKET, type, htons(protocol)), 50 SyscallFailsWithErrno(EPERM)); 51 GTEST_SKIP() << "Missing packet socket capability"; 52 } 53 } 54 }; 55 56 TEST_P(PacketSocketCreationTest, Create) { 57 const auto [type, protocol] = GetParam(); 58 FileDescriptor fd = 59 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_PACKET, type, htons(protocol))); 60 EXPECT_GE(fd.get(), 0); 61 } 62 63 INSTANTIATE_TEST_SUITE_P(AllPacketSocketTests, PacketSocketCreationTest, 64 Combine(Values(SOCK_DGRAM, SOCK_RAW), 65 Values(0, 1, 255, ETH_P_IP, ETH_P_IPV6, 66 std::numeric_limits<uint16_t>::max()))); 67 68 class PacketSocketTest : public ::testing::TestWithParam<int> { 69 protected: 70 void SetUp() override { 71 if (!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())) { 72 ASSERT_THAT(socket(AF_PACKET, GetParam(), 0), 73 SyscallFailsWithErrno(EPERM)); 74 GTEST_SKIP() << "Missing packet socket capability"; 75 } 76 77 socket_ = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_PACKET, GetParam(), 0)); 78 } 79 80 FileDescriptor socket_; 81 }; 82 83 TEST_P(PacketSocketTest, GetSockName) { 84 { 85 // First check the local address of an unbound packet socket. 86 sockaddr_ll addr; 87 socklen_t addrlen = sizeof(addr); 88 ASSERT_THAT(getsockname(socket_.get(), reinterpret_cast<sockaddr*>(&addr), 89 &addrlen), 90 SyscallSucceeds()); 91 // sockaddr_ll ends with an 8 byte physical address field, but only the 92 // bytes that are used in the sockaddr_ll.sll_addr field are included in the 93 // address length. Seems Linux used to return the size of sockaddr_ll, but 94 // https://github.com/torvalds/linux/commit/0fb375fb9b93b7d822debc6a734052337ccfdb1f 95 // changed things to only return `sizeof(sockaddr_ll) + sll.sll_addr`. 96 ASSERT_THAT(addrlen, AnyOf(Eq(sizeof(addr)), 97 Eq(sizeof(addr) - sizeof(addr.sll_addr)))); 98 EXPECT_EQ(addr.sll_family, AF_PACKET); 99 EXPECT_EQ(addr.sll_ifindex, 0); 100 101 if (IsRunningOnGvisor() && !IsRunningWithHostinet() && 102 GvisorPlatform() != Platform::kFuchsia) { 103 // TODO(https://gvisor.dev/issue/6530): Do not assume all interfaces have 104 // an ethernet address. 105 EXPECT_EQ(addr.sll_halen, ETH_ALEN); 106 } else { 107 EXPECT_EQ(addr.sll_halen, 0); 108 } 109 EXPECT_EQ(ntohs(addr.sll_protocol), 0); 110 EXPECT_EQ(addr.sll_hatype, 0); 111 } 112 // Next we bind the socket to loopback before checking the local address. 113 const sockaddr_ll bind_addr = { 114 .sll_family = AF_PACKET, 115 .sll_protocol = htons(ETH_P_IP), 116 .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()), 117 }; 118 ASSERT_THAT(bind(socket_.get(), reinterpret_cast<const sockaddr*>(&bind_addr), 119 sizeof(bind_addr)), 120 SyscallSucceeds()); 121 { 122 sockaddr_ll addr; 123 socklen_t addrlen = sizeof(addr); 124 ASSERT_THAT(getsockname(socket_.get(), reinterpret_cast<sockaddr*>(&addr), 125 &addrlen), 126 SyscallSucceeds()); 127 ASSERT_THAT(addrlen, 128 AnyOf(Eq(sizeof(addr)), 129 Eq(sizeof(addr) - sizeof(addr.sll_addr) + ETH_ALEN))); 130 EXPECT_EQ(addr.sll_family, AF_PACKET); 131 EXPECT_EQ(addr.sll_ifindex, bind_addr.sll_ifindex); 132 EXPECT_EQ(addr.sll_halen, ETH_ALEN); 133 // Bound to loopback which has the all zeroes address. 134 for (int i = 0; i < addr.sll_halen; ++i) { 135 EXPECT_EQ(addr.sll_addr[i], 0) << "byte mismatch @ idx = " << i; 136 } 137 EXPECT_EQ(ntohs(addr.sll_protocol), htons(addr.sll_protocol)); 138 if (IsRunningOnGvisor() && !IsRunningWithHostinet() && 139 GvisorPlatform() != Platform::kFuchsia) { 140 // TODO(https://gvisor.dev/issue/6621): Support populating sll_hatype. 141 EXPECT_EQ(addr.sll_hatype, 0); 142 } else { 143 EXPECT_EQ(addr.sll_hatype, ARPHRD_LOOPBACK); 144 } 145 } 146 } 147 148 // Expects that a packet can be read from the given packet socket that contains 149 // a UDP packet whose source and destination port match the one in the given 150 // address, and whose payload matches the expected payload. 151 // 152 // On success, writes the link-layer source address for the packet into 153 // the provided output parameter (if it is non-null). 154 void ExpectReceiveOnPacketSocket(FileDescriptor& socket, 155 bool ethernet_header_included, 156 const sockaddr_in& expected_udp_addr, 157 const uint64_t expected_udp_payload, 158 sockaddr_ll* src_out = nullptr) { 159 // Declare each section of the packet as a separate stack variable in order 160 // to ensure all sections are 8-byte aligned. 161 ethhdr eth; 162 iphdr ip; 163 udphdr udp; 164 uint64_t payload; 165 char unused; 166 167 constexpr size_t kStorageLen = 168 sizeof(eth) + sizeof(ip) + sizeof(udp) + sizeof(payload) + sizeof(unused); 169 char storage[kStorageLen]; 170 171 sockaddr_ll src; 172 socklen_t src_len = sizeof(src); 173 174 char* buf = storage; 175 size_t buflen = kStorageLen; 176 auto advance_buf = [&buf, &buflen](size_t amount) { 177 buf += amount; 178 buflen -= amount; 179 }; 180 size_t expected_read_len = buflen - sizeof(unused); 181 if (!ethernet_header_included) { 182 advance_buf(sizeof(eth)); 183 expected_read_len -= sizeof(eth); 184 } 185 186 iovec received_iov = { 187 .iov_base = buf, 188 .iov_len = buflen, 189 }; 190 msghdr received_msg = { 191 .msg_name = &src, 192 .msg_namelen = src_len, 193 .msg_iov = &received_iov, 194 .msg_iovlen = 1, 195 }; 196 197 // NB: poll indefinitely on Fuchsia to avoid timing out in Infra. 198 int timeout = GvisorPlatform() == Platform::kFuchsia ? -1 : 1; 199 ASSERT_THAT(RecvMsgTimeout(socket.get(), &received_msg, timeout), 200 IsPosixErrorOkAndHolds(expected_read_len)); 201 202 // sockaddr_ll ends with an 8 byte physical address field, but ethernet 203 // addresses only use 6 bytes. Linux used to return sizeof(sockaddr_ll)-2 204 // here, but returns sizeof(sockaddr_ll) since 205 // https://github.com/torvalds/linux/commit/b2cf86e1563e33a14a1c69b3e508d15dc12f804c. 206 ASSERT_THAT(received_msg.msg_namelen, 207 AnyOf(Eq(sizeof(src)), 208 Eq(sizeof(src) - sizeof(src.sll_addr) + ETH_ALEN))); 209 EXPECT_EQ(src.sll_family, AF_PACKET); 210 EXPECT_EQ(src.sll_ifindex, ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex())); 211 EXPECT_EQ(src.sll_halen, ETH_ALEN); 212 EXPECT_EQ(ntohs(src.sll_protocol), ETH_P_IP); 213 // This came from the loopback device, so the address is all 0s. 214 constexpr uint8_t allZeroesMAC[ETH_ALEN] = {}; 215 EXPECT_EQ(memcmp(src.sll_addr, allZeroesMAC, sizeof(allZeroesMAC)), 0); 216 217 if (ethernet_header_included) { 218 memcpy(ð, buf, sizeof(eth)); 219 EXPECT_EQ(memcmp(eth.h_dest, allZeroesMAC, sizeof(allZeroesMAC)), 0); 220 EXPECT_EQ(memcmp(eth.h_source, allZeroesMAC, sizeof(allZeroesMAC)), 0); 221 EXPECT_EQ(ntohs(eth.h_proto), ETH_P_IP); 222 advance_buf(sizeof(eth)); 223 } 224 225 // IHL hold the size of the header in 4 byte units. 226 memcpy(&ip, buf, sizeof(ip)); 227 EXPECT_EQ(ip.ihl, sizeof(iphdr) / 4); 228 EXPECT_EQ(ip.version, IPVERSION); 229 const uint16_t ip_pkt_size = sizeof(ip) + sizeof(udp) + sizeof(payload); 230 EXPECT_EQ(ntohs(ip.tot_len), ip_pkt_size); 231 EXPECT_EQ(ip.protocol, IPPROTO_UDP); 232 EXPECT_EQ(ntohl(ip.daddr), INADDR_LOOPBACK); 233 EXPECT_EQ(ntohl(ip.saddr), INADDR_LOOPBACK); 234 advance_buf(sizeof(ip)); 235 236 memcpy(&udp, buf, sizeof(udp)); 237 EXPECT_EQ(udp.source, expected_udp_addr.sin_port); 238 EXPECT_EQ(udp.dest, expected_udp_addr.sin_port); 239 EXPECT_EQ(ntohs(udp.len), ip_pkt_size - sizeof(ip)); 240 advance_buf(sizeof(udp)); 241 242 memcpy(&payload, buf, sizeof(payload)); 243 EXPECT_EQ(payload, expected_udp_payload); 244 if (src_out) { 245 *src_out = src; 246 } 247 } 248 249 TEST_P(PacketSocketTest, RebindProtocol) { 250 const bool kEthHdrIncluded = GetParam() == SOCK_RAW; 251 252 sockaddr_in udp_bind_addr = { 253 .sin_family = AF_INET, 254 .sin_addr = {.s_addr = htonl(INADDR_LOOPBACK)}, 255 }; 256 257 FileDescriptor udp_sock = 258 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); 259 { 260 // Bind the socket so that we have something to send packets to. 261 // 262 // If we didn't do this, the UDP packets we send will be responded to with 263 // ICMP Destination Port Unreachable errors. 264 ASSERT_THAT( 265 bind(udp_sock.get(), reinterpret_cast<const sockaddr*>(&udp_bind_addr), 266 sizeof(udp_bind_addr)), 267 SyscallSucceeds()); 268 socklen_t addrlen = sizeof(udp_bind_addr); 269 ASSERT_THAT( 270 getsockname(udp_sock.get(), reinterpret_cast<sockaddr*>(&udp_bind_addr), 271 &addrlen), 272 SyscallSucceeds()); 273 ASSERT_THAT(addrlen, sizeof(udp_bind_addr)); 274 } 275 276 const int loopback_index = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()); 277 278 auto send_udp_message = [&](const uint64_t v) { 279 ASSERT_THAT( 280 sendto(udp_sock.get(), reinterpret_cast<const char*>(&v), sizeof(v), 281 0 /* flags */, reinterpret_cast<const sockaddr*>(&udp_bind_addr), 282 sizeof(udp_bind_addr)), 283 SyscallSucceeds()); 284 285 // Make sure the payload has been delivered (in case of asynchronous 286 // delivery). 287 char buf[sizeof(v)]; 288 // NB: poll indefinitely on Fuchsia to avoid timing out in Infra. 289 int timeout = GvisorPlatform() == Platform::kFuchsia ? -1 : 1; 290 EXPECT_THAT(RecvTimeout(udp_sock.get(), buf, sizeof(v), timeout), 291 IsPosixErrorOkAndHolds(sizeof(v))); 292 ASSERT_EQ(*reinterpret_cast<uint64_t*>(buf), v); 293 }; 294 295 auto bind_to_network_protocol = [&](uint16_t protocol) { 296 const sockaddr_ll packet_bind_addr = { 297 .sll_family = AF_PACKET, 298 .sll_protocol = htons(protocol), 299 .sll_ifindex = loopback_index, 300 }; 301 302 ASSERT_THAT(bind(socket_.get(), 303 reinterpret_cast<const sockaddr*>(&packet_bind_addr), 304 sizeof(packet_bind_addr)), 305 SyscallSucceeds()); 306 }; 307 308 // The packet socket is not bound to IPv4 so we should not receive the sent 309 // message. 310 uint64_t counter = 0; 311 ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter)); 312 313 // Bind to IPv4 and expect to receive the UDP packet we send after binding. 314 ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(ETH_P_IP)); 315 ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter)); 316 ASSERT_NO_FATAL_FAILURE(ExpectReceiveOnPacketSocket(socket_, kEthHdrIncluded, 317 udp_bind_addr, counter)); 318 319 // Bind the packet socket to a random protocol. 320 ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(255)); 321 ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter)); 322 323 // Bind back to IPv4 and expect to the UDP packet we send after binding 324 // back to IPv4. 325 ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(ETH_P_IP)); 326 ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter)); 327 ASSERT_NO_FATAL_FAILURE(ExpectReceiveOnPacketSocket(socket_, kEthHdrIncluded, 328 udp_bind_addr, counter)); 329 330 // A zero valued protocol number should not change the bound network protocol. 331 ASSERT_NO_FATAL_FAILURE(bind_to_network_protocol(0)); 332 ASSERT_NO_FATAL_FAILURE(send_udp_message(++counter)); 333 ASSERT_NO_FATAL_FAILURE(ExpectReceiveOnPacketSocket(socket_, kEthHdrIncluded, 334 udp_bind_addr, counter)); 335 } 336 337 // Receive sent frames when bound to ETH_P_ALL. 338 TEST_P(PacketSocketTest, ReceiveSentBoundToProtocolAll) { 339 // If a packet socket is bound to the loopback interface with protocol 340 // ETH_P_ALL, it should receive a frame that is sent twice: once on sending 341 // and again on reception. 342 343 sockaddr_in udp_bind_addr = { 344 .sin_family = AF_INET, 345 .sin_addr = {.s_addr = htonl(INADDR_LOOPBACK)}, 346 }; 347 348 FileDescriptor udp_sock = 349 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); 350 { 351 // Bind the socket so that we have something to send packets to. 352 // 353 // If we didn't do this, the UDP packets we send will be responded to with 354 // ICMP Destination Port Unreachable errors. 355 ASSERT_THAT( 356 bind(udp_sock.get(), reinterpret_cast<const sockaddr*>(&udp_bind_addr), 357 sizeof(udp_bind_addr)), 358 SyscallSucceeds()); 359 socklen_t addrlen = sizeof(udp_bind_addr); 360 ASSERT_THAT( 361 getsockname(udp_sock.get(), reinterpret_cast<sockaddr*>(&udp_bind_addr), 362 &addrlen), 363 SyscallSucceeds()); 364 ASSERT_THAT(addrlen, sizeof(udp_bind_addr)); 365 ASSERT_NE(udp_bind_addr.sin_port, 0); 366 } 367 368 // Bind the packet socket to the loopback interface with ETH_P_ALL. 369 const struct sockaddr_ll bind_addr = { 370 .sll_family = AF_PACKET, 371 .sll_protocol = htons(ETH_P_ALL), 372 .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()), 373 .sll_halen = ETH_ALEN, 374 }; 375 ASSERT_THAT(bind(socket_.get(), reinterpret_cast<const sockaddr*>(&bind_addr), 376 sizeof(bind_addr)), 377 SyscallSucceeds()); 378 379 const uint64_t kContents = 0xAAAAAAAAAAAAAAAA; 380 381 // Send to the same UDP socket so we don't interfere with other tests. 382 ASSERT_THAT(sendto(udp_sock.get(), &kContents, sizeof(kContents), 0, 383 reinterpret_cast<const struct sockaddr*>(&udp_bind_addr), 384 sizeof(udp_bind_addr)), 385 SyscallSucceeds()); 386 387 const bool kExpectEthernetHeader = GetParam() == SOCK_RAW; 388 sockaddr_ll src_addr; 389 390 // Receive the outgoing frame. 391 ExpectReceiveOnPacketSocket(socket_, kExpectEthernetHeader, udp_bind_addr, 392 kContents, &src_addr); 393 ASSERT_EQ(src_addr.sll_pkttype, PACKET_OUTGOING); 394 395 // Then receive the incoming frame. 396 ExpectReceiveOnPacketSocket(socket_, kExpectEthernetHeader, udp_bind_addr, 397 kContents, &src_addr); 398 ASSERT_EQ(src_addr.sll_pkttype, PACKET_HOST); 399 } 400 401 // Verify that the ifindex field of sockaddr_ll must be provided when calling 402 // sendto on a packet socket (e.g. the interface cannot be inferred from the 403 // bound address). 404 TEST_P(PacketSocketTest, SendWithoutTargetDevice) { 405 if (IsRunningOnGvisor() && GvisorPlatform() != Platform::kFuchsia) { 406 GTEST_SKIP() << "gVisor does not support sending on packet sockets."; 407 } 408 409 const uint16_t kArbitraryProtocol = 0xFFFF; 410 411 // Bind the packet socket to the loopback interface. Despite this, subsequent 412 // sends will require the interface be specified. 413 const struct sockaddr_ll bind_addr = { 414 .sll_family = AF_PACKET, 415 .sll_protocol = htons(kArbitraryProtocol), 416 .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()), 417 .sll_halen = ETH_ALEN, 418 }; 419 ASSERT_THAT(bind(socket_.get(), reinterpret_cast<const sockaddr*>(&bind_addr), 420 sizeof(bind_addr)), 421 SyscallSucceeds()); 422 423 // Prepare a send buffer with a valid Ethernet header. 424 // This enables sending with SOCK_RAW, and is inconsequential for SOCK_DGRAM. 425 const uint64_t kContents = 0xAAAAAAAAAAAAAAAA; 426 struct ethhdr eth = {}; 427 eth.h_proto = htons(kArbitraryProtocol); 428 char send_buf[sizeof(eth) + sizeof(kContents)]; 429 memcpy(send_buf, ð, sizeof(eth)); 430 memcpy(send_buf + sizeof(ethhdr), &kContents, sizeof(kContents)); 431 432 // Send to a valid address. 433 const struct sockaddr_ll valid_addr = { 434 .sll_family = AF_PACKET, 435 .sll_protocol = htons(kArbitraryProtocol), 436 .sll_ifindex = ASSERT_NO_ERRNO_AND_VALUE(GetLoopbackIndex()), 437 .sll_halen = ETH_ALEN, 438 }; 439 ASSERT_THAT(sendto(socket_.get(), send_buf, sizeof(send_buf), 0, 440 reinterpret_cast<const struct sockaddr*>(&valid_addr), 441 sizeof(valid_addr)), 442 SyscallSucceedsWithValue(sizeof(send_buf))); 443 444 // Attempt to send without specifying the interface. 445 const struct sockaddr_ll no_dev_addr = { 446 .sll_family = AF_PACKET, 447 .sll_protocol = htons(kArbitraryProtocol), 448 .sll_ifindex = 0, 449 .sll_halen = ETH_ALEN, 450 }; 451 ASSERT_THAT(sendto(socket_.get(), send_buf, sizeof(send_buf), 0, 452 reinterpret_cast<const struct sockaddr*>(&no_dev_addr), 453 sizeof(no_dev_addr)), 454 SyscallFailsWithErrno(ENXIO)); 455 } 456 457 INSTANTIATE_TEST_SUITE_P(AllPacketSocketTests, PacketSocketTest, 458 Values(SOCK_DGRAM, SOCK_RAW)); 459 460 } // namespace 461 462 } // namespace testing 463 } // namespace gvisor