gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/packet_socket_raw.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 <errno.h> 17 #include <net/ethernet.h> 18 #include <net/if_arp.h> 19 #include <netinet/in.h> 20 #include <netinet/ip.h> 21 #include <netinet/udp.h> 22 #include <netpacket/packet.h> 23 #include <poll.h> 24 #include <sys/socket.h> 25 #include <sys/types.h> 26 #include <unistd.h> 27 28 #include <functional> 29 30 #include "gmock/gmock.h" 31 #include "gtest/gtest.h" 32 #include "absl/base/internal/endian.h" 33 #include "test/syscalls/linux/ip_socket_test_util.h" 34 #include "test/syscalls/linux/unix_domain_socket_test_util.h" 35 #include "test/util/capability_util.h" 36 #include "test/util/cleanup.h" 37 #include "test/util/file_descriptor.h" 38 #include "test/util/posix_error.h" 39 #include "test/util/socket_util.h" 40 #include "test/util/test_util.h" 41 42 // Some of these tests involve sending packets via AF_PACKET sockets and the 43 // loopback interface. Because AF_PACKET circumvents so much of the networking 44 // stack, Linux sees these packets as "martian", i.e. they claim to be to/from 45 // localhost but don't have the usual associated data. Thus Linux drops them by 46 // default. You can see where this happens by following the code at: 47 // 48 // - net/ipv4/ip_input.c:ip_rcv_finish, which calls 49 // - net/ipv4/route.c:ip_route_input_noref, which calls 50 // - net/ipv4/route.c:ip_route_input_slow, which finds and drops martian 51 // packets. 52 // 53 // To tell Linux not to drop these packets, you need to tell it to accept our 54 // funny packets (which are completely valid and correct, but lack associated 55 // in-kernel data because we use AF_PACKET): 56 // 57 // echo 1 >> /proc/sys/net/ipv4/conf/lo/accept_local 58 // echo 1 >> /proc/sys/net/ipv4/conf/lo/route_localnet 59 // 60 // These tests require CAP_NET_RAW to run. 61 62 namespace gvisor { 63 namespace testing { 64 65 namespace { 66 67 using ::testing::AnyOf; 68 using ::testing::Eq; 69 70 constexpr char kMessage[] = "soweoneul malhaebwa"; 71 constexpr in_port_t kPort = 0x409c; // htons(40000) 72 73 // Send kMessage via sock to loopback 74 void SendUDPMessage(int sock) { 75 struct sockaddr_in dest = {}; 76 dest.sin_port = kPort; 77 dest.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 78 dest.sin_family = AF_INET; 79 EXPECT_THAT(sendto(sock, kMessage, sizeof(kMessage), 0, 80 reinterpret_cast<struct sockaddr*>(&dest), sizeof(dest)), 81 SyscallSucceedsWithValue(sizeof(kMessage))); 82 } 83 84 // 85 // Raw tests. Packets sent with raw AF_PACKET sockets always include link layer 86 // headers. 87 // 88 89 // Tests for "raw" (SOCK_RAW) packet(7) sockets. 90 class RawPacketTest : public ::testing::TestWithParam<int> { 91 protected: 92 // Creates a socket to be used in tests. 93 void SetUp() override; 94 95 // Closes the socket created by SetUp(). 96 void TearDown() override; 97 98 // Gets the device index of the loopback device. 99 int GetLoopbackIndex(); 100 101 // The socket used for both reading and writing. 102 int s_; 103 104 // The function to restore the original system configuration. 105 std::function<PosixError()> restore_config_; 106 }; 107 108 void RawPacketTest::SetUp() { 109 if (!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())) { 110 ASSERT_THAT(socket(AF_PACKET, SOCK_RAW, htons(GetParam())), 111 SyscallFailsWithErrno(EPERM)); 112 GTEST_SKIP(); 113 } 114 115 ASSERT_THAT(s_ = socket(AF_PACKET, SOCK_RAW, htons(GetParam())), 116 SyscallSucceeds()); 117 118 auto restore_config = AllowMartianPacketsOnLoopback(); 119 if (restore_config.ok()) { 120 restore_config_ = restore_config.ValueOrDie(); 121 } else { 122 ASSERT_THAT(restore_config.error(), PosixErrorIs(EACCES)); 123 GTEST_SKIP(); 124 } 125 } 126 127 void RawPacketTest::TearDown() { 128 if (restore_config_) { 129 EXPECT_NO_ERRNO(restore_config_()); 130 } 131 132 // TearDown will be run even if we skip the test. 133 if (ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())) { 134 EXPECT_THAT(close(s_), SyscallSucceeds()); 135 } 136 } 137 138 int RawPacketTest::GetLoopbackIndex() { 139 int v = EXPECT_NO_ERRNO_AND_VALUE(gvisor::testing::GetLoopbackIndex()); 140 EXPECT_NE(v, 0); 141 return v; 142 } 143 144 // Receive via a packet socket. 145 TEST_P(RawPacketTest, Receive) { 146 // Let's use a simple IP payload: a UDP datagram. 147 FileDescriptor udp_sock = 148 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); 149 SendUDPMessage(udp_sock.get()); 150 151 // Wait for the socket to become readable. 152 struct pollfd pfd = {}; 153 pfd.fd = s_; 154 pfd.events = POLLIN; 155 EXPECT_THAT(RetryEINTR(poll)(&pfd, 1, 2000), SyscallSucceedsWithValue(1)); 156 157 // Read and verify the data. 158 constexpr size_t packet_size = sizeof(struct ethhdr) + sizeof(struct iphdr) + 159 sizeof(struct udphdr) + sizeof(kMessage); 160 char buf[64]; 161 struct sockaddr_ll src = {}; 162 socklen_t src_len = sizeof(src); 163 ASSERT_THAT(recvfrom(s_, buf, sizeof(buf), 0, 164 reinterpret_cast<struct sockaddr*>(&src), &src_len), 165 SyscallSucceedsWithValue(packet_size)); 166 // sockaddr_ll ends with an 8 byte physical address field, but ethernet 167 // addresses only use 6 bytes. Linux used to return sizeof(sockaddr_ll)-2 168 // here, but since commit b2cf86e1563e33a14a1c69b3e508d15dc12f804c returns 169 // sizeof(sockaddr_ll). 170 ASSERT_THAT(src_len, AnyOf(Eq(sizeof(src)), Eq(sizeof(src) - 2))); 171 172 // Verify the source address. 173 EXPECT_EQ(src.sll_family, AF_PACKET); 174 EXPECT_EQ(src.sll_ifindex, GetLoopbackIndex()); 175 EXPECT_EQ(src.sll_halen, ETH_ALEN); 176 EXPECT_EQ(ntohs(src.sll_protocol), ETH_P_IP); 177 // This came from the loopback device, so the address is all 0s. 178 for (int i = 0; i < src.sll_halen; i++) { 179 EXPECT_EQ(src.sll_addr[i], 0); 180 } 181 182 // Verify the ethernet header. We memcpy to deal with pointer alignment. 183 struct ethhdr eth = {}; 184 memcpy(ð, buf, sizeof(eth)); 185 // The destination and source address should be 0, for loopback. 186 for (int i = 0; i < ETH_ALEN; i++) { 187 EXPECT_EQ(eth.h_dest[i], 0); 188 EXPECT_EQ(eth.h_source[i], 0); 189 } 190 EXPECT_EQ(eth.h_proto, htons(ETH_P_IP)); 191 192 // Verify the IP header. We memcpy to deal with pointer aligment. 193 struct iphdr ip = {}; 194 memcpy(&ip, buf + sizeof(ethhdr), sizeof(ip)); 195 EXPECT_EQ(ip.ihl, 5); 196 EXPECT_EQ(ip.version, 4); 197 EXPECT_EQ(ip.tot_len, htons(packet_size - sizeof(eth))); 198 EXPECT_EQ(ip.protocol, IPPROTO_UDP); 199 EXPECT_EQ(ip.daddr, htonl(INADDR_LOOPBACK)); 200 EXPECT_EQ(ip.saddr, htonl(INADDR_LOOPBACK)); 201 202 // Verify the UDP header. We memcpy to deal with pointer aligment. 203 struct udphdr udp = {}; 204 memcpy(&udp, buf + sizeof(eth) + sizeof(iphdr), sizeof(udp)); 205 EXPECT_EQ(udp.dest, kPort); 206 EXPECT_EQ(udp.len, htons(sizeof(udphdr) + sizeof(kMessage))); 207 208 // Verify the payload. 209 char* payload = reinterpret_cast<char*>(buf + sizeof(eth) + sizeof(iphdr) + 210 sizeof(udphdr)); 211 EXPECT_EQ(strncmp(payload, kMessage, sizeof(kMessage)), 0); 212 } 213 214 void ValidateSend(int sendfd, in_addr_t src_addr, int dst_ifindex) { 215 // TODO(b/267210840): Fix this test for hostinet. Something is wrong with 216 // poll(). 217 SKIP_IF(IsRunningWithHostinet()); 218 219 // Let's send a UDP packet and receive it using a regular UDP socket. 220 FileDescriptor udp_sock = 221 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0)); 222 struct sockaddr_in bind_addr = {}; 223 bind_addr.sin_family = AF_INET; 224 bind_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 225 bind_addr.sin_port = kPort; 226 ASSERT_THAT( 227 bind(udp_sock.get(), reinterpret_cast<struct sockaddr*>(&bind_addr), 228 sizeof(bind_addr)), 229 SyscallSucceeds()); 230 231 // Set up the destination physical address. 232 struct sockaddr_ll dest = {}; 233 dest.sll_family = AF_PACKET; 234 dest.sll_halen = ETH_ALEN; 235 dest.sll_ifindex = dst_ifindex; 236 dest.sll_protocol = htons(ETH_P_IP); 237 // We're sending to the loopback device, so the address is all 0s. 238 memset(dest.sll_addr, 0x00, ETH_ALEN); 239 240 // Set up the ethernet header. The kernel takes care of the footer. 241 // We're sending to and from hardware address 0 (loopback). 242 struct ethhdr eth = {}; 243 eth.h_proto = htons(ETH_P_IP); 244 245 // Set up the IP header. 246 struct iphdr iphdr = {}; 247 iphdr.ihl = 5; 248 iphdr.version = 4; 249 iphdr.tos = 0; 250 iphdr.tot_len = 251 htons(sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kMessage)); 252 // Get a pseudo-random ID. If we clash with an in-use ID the test will fail, 253 // but we have no way of getting an ID we know to be good. 254 srand(*reinterpret_cast<unsigned int*>(&iphdr)); 255 iphdr.id = rand(); 256 // Linux sets this bit ("do not fragment") for small packets. 257 iphdr.frag_off = 1 << 6; 258 iphdr.ttl = 64; 259 iphdr.protocol = IPPROTO_UDP; 260 iphdr.daddr = htonl(INADDR_LOOPBACK); 261 iphdr.saddr = htonl(src_addr); 262 iphdr.check = IPChecksum(iphdr); 263 264 // Set up the UDP header. 265 struct udphdr udphdr = {}; 266 udphdr.source = kPort; 267 udphdr.dest = kPort; 268 udphdr.len = htons(sizeof(udphdr) + sizeof(kMessage)); 269 udphdr.check = UDPChecksum(iphdr, udphdr, kMessage, sizeof(kMessage)); 270 271 // Copy both headers and the payload into our packet buffer. 272 char 273 send_buf[sizeof(eth) + sizeof(iphdr) + sizeof(udphdr) + sizeof(kMessage)]; 274 memcpy(send_buf, ð, sizeof(eth)); 275 memcpy(send_buf + sizeof(ethhdr), &iphdr, sizeof(iphdr)); 276 memcpy(send_buf + sizeof(ethhdr) + sizeof(iphdr), &udphdr, sizeof(udphdr)); 277 memcpy(send_buf + sizeof(ethhdr) + sizeof(iphdr) + sizeof(udphdr), kMessage, 278 sizeof(kMessage)); 279 280 // Send it. 281 ASSERT_THAT(sendto(sendfd, send_buf, sizeof(send_buf), 0, 282 reinterpret_cast<struct sockaddr*>(&dest), sizeof(dest)), 283 SyscallSucceedsWithValue(sizeof(send_buf))); 284 285 // Wait for the packet to become available on both sockets. 286 struct pollfd pfd = {}; 287 pfd.fd = udp_sock.get(); 288 pfd.events = POLLIN; 289 ASSERT_THAT(RetryEINTR(poll)(&pfd, 1, 5000), SyscallSucceedsWithValue(1)); 290 pfd.fd = sendfd; 291 pfd.events = POLLIN; 292 ASSERT_THAT(RetryEINTR(poll)(&pfd, 1, 5000), SyscallSucceedsWithValue(1)); 293 294 // Receive on the packet socket. 295 char recv_buf[sizeof(send_buf)]; 296 ASSERT_THAT(recv(sendfd, recv_buf, sizeof(recv_buf), 0), 297 SyscallSucceedsWithValue(sizeof(recv_buf))); 298 ASSERT_EQ(memcmp(recv_buf, send_buf, sizeof(send_buf)), 0); 299 300 // Receive on the UDP socket. 301 struct sockaddr_in src; 302 socklen_t src_len = sizeof(src); 303 ASSERT_THAT(recvfrom(udp_sock.get(), recv_buf, sizeof(recv_buf), MSG_DONTWAIT, 304 reinterpret_cast<struct sockaddr*>(&src), &src_len), 305 SyscallSucceedsWithValue(sizeof(kMessage))); 306 // Check src and payload. 307 EXPECT_EQ(strncmp(recv_buf, kMessage, sizeof(kMessage)), 0); 308 EXPECT_EQ(src.sin_family, AF_INET); 309 EXPECT_EQ(src.sin_port, kPort); 310 EXPECT_EQ(src.sin_addr.s_addr, htonl(src_addr)); 311 } 312 313 // Send via a packet socket. 314 TEST_P(RawPacketTest, SendFromLoopback) { 315 ASSERT_NO_FATAL_FAILURE( 316 ValidateSend(s_, INADDR_LOOPBACK, GetLoopbackIndex())); 317 } 318 319 TEST_P(RawPacketTest, SendFromUnspec) { 320 ASSERT_NO_FATAL_FAILURE(ValidateSend(s_, INADDR_ANY, GetLoopbackIndex())); 321 } 322 323 // Check that setting SO_RCVBUF below min is clamped to the minimum 324 // receive buffer size. 325 TEST_P(RawPacketTest, SetSocketRecvBufBelowMin) { 326 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 327 328 // Discover minimum receive buf size by trying to set it to zero. 329 // See: 330 // https://github.com/torvalds/linux/blob/a5dc8300df75e8b8384b4c82225f1e4a0b4d9b55/net/core/sock.c#L820 331 constexpr int kRcvBufSz = 0; 332 ASSERT_THAT( 333 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &kRcvBufSz, sizeof(kRcvBufSz)), 334 SyscallSucceeds()); 335 336 int min = 0; 337 socklen_t min_len = sizeof(min); 338 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &min, &min_len), 339 SyscallSucceeds()); 340 341 // Linux doubles the value so let's use a value that when doubled will still 342 // be smaller than min. 343 int below_min = min / 2 - 1; 344 ASSERT_THAT( 345 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &below_min, sizeof(below_min)), 346 SyscallSucceeds()); 347 348 int val = 0; 349 socklen_t val_len = sizeof(val); 350 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &val, &val_len), 351 SyscallSucceeds()); 352 353 ASSERT_EQ(min, val); 354 } 355 356 // Check that setting SO_RCVBUF above max is clamped to the maximum 357 // receive buffer size. 358 TEST_P(RawPacketTest, SetSocketRecvBufAboveMax) { 359 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 360 361 // Discover max buf size by trying to set the largest possible buffer size. 362 constexpr int kRcvBufSz = 0xffffffff; 363 ASSERT_THAT( 364 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &kRcvBufSz, sizeof(kRcvBufSz)), 365 SyscallSucceeds()); 366 367 int max = 0; 368 socklen_t max_len = sizeof(max); 369 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &max, &max_len), 370 SyscallSucceeds()); 371 372 int above_max = max + 1; 373 ASSERT_THAT( 374 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &above_max, sizeof(above_max)), 375 SyscallSucceeds()); 376 377 int val = 0; 378 socklen_t val_len = sizeof(val); 379 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &val, &val_len), 380 SyscallSucceeds()); 381 ASSERT_EQ(max, val); 382 } 383 384 // Check that setting SO_RCVBUF min <= kRcvBufSz <= max is honored. 385 TEST_P(RawPacketTest, SetSocketRecvBuf) { 386 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 387 388 int max = 0; 389 int min = 0; 390 { 391 // Discover max buf size by trying to set a really large buffer size. 392 constexpr int kRcvBufSz = 0xffffffff; 393 ASSERT_THAT( 394 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &kRcvBufSz, sizeof(kRcvBufSz)), 395 SyscallSucceeds()); 396 397 max = 0; 398 socklen_t max_len = sizeof(max); 399 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &max, &max_len), 400 SyscallSucceeds()); 401 } 402 403 { 404 // Discover minimum buffer size by trying to set a zero size receive buffer 405 // size. 406 // See: 407 // https://github.com/torvalds/linux/blob/a5dc8300df75e8b8384b4c82225f1e4a0b4d9b55/net/core/sock.c#L820 408 constexpr int kRcvBufSz = 0; 409 ASSERT_THAT( 410 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &kRcvBufSz, sizeof(kRcvBufSz)), 411 SyscallSucceeds()); 412 413 socklen_t min_len = sizeof(min); 414 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &min, &min_len), 415 SyscallSucceeds()); 416 } 417 418 const int quarter_sz = min + (max - min) / 4; 419 ASSERT_THAT( 420 setsockopt(s_, SOL_SOCKET, SO_RCVBUF, &quarter_sz, sizeof(quarter_sz)), 421 SyscallSucceeds()); 422 423 int val = 0; 424 socklen_t val_len = sizeof(val); 425 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_RCVBUF, &val, &val_len), 426 SyscallSucceeds()); 427 428 #ifndef __Fuchsia__ 429 ASSERT_EQ(val, quarter_sz * 2); 430 #else 431 ASSERT_THAT(val, AnyOf(quarter_sz, quarter_sz * 2)); 432 #endif // __Fuchsia__ 433 } 434 435 // Check that setting SO_SNDBUF below min is clamped to the minimum 436 // receive buffer size. 437 TEST_P(RawPacketTest, SetSocketSendBufBelowMin) { 438 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 439 440 // Discover minimum buffer size by trying to set it to zero. 441 constexpr int kSndBufSz = 0; 442 ASSERT_THAT( 443 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &kSndBufSz, sizeof(kSndBufSz)), 444 SyscallSucceeds()); 445 446 int min = 0; 447 socklen_t min_len = sizeof(min); 448 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &min, &min_len), 449 SyscallSucceeds()); 450 451 // Linux doubles the value so let's use a value that when doubled will still 452 // be smaller than min. 453 int below_min = min / 2 - 1; 454 ASSERT_THAT( 455 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &below_min, sizeof(below_min)), 456 SyscallSucceeds()); 457 458 int val = 0; 459 socklen_t val_len = sizeof(val); 460 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &val, &val_len), 461 SyscallSucceeds()); 462 463 ASSERT_EQ(min, val); 464 } 465 466 // Check that setting SO_SNDBUF above max is clamped to the maximum 467 // send buffer size. 468 TEST_P(RawPacketTest, SetSocketSendBufAboveMax) { 469 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 470 471 // Discover maximum buffer size by trying to set it to a large value. 472 constexpr int kSndBufSz = 0xffffffff; 473 ASSERT_THAT( 474 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &kSndBufSz, sizeof(kSndBufSz)), 475 SyscallSucceeds()); 476 477 int max = 0; 478 socklen_t max_len = sizeof(max); 479 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &max, &max_len), 480 SyscallSucceeds()); 481 482 int above_max = max + 1; 483 ASSERT_THAT( 484 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &above_max, sizeof(above_max)), 485 SyscallSucceeds()); 486 487 int val = 0; 488 socklen_t val_len = sizeof(val); 489 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &val, &val_len), 490 SyscallSucceeds()); 491 ASSERT_EQ(max, val); 492 } 493 494 // Check that setting SO_SNDBUF min <= kSndBufSz <= max is honored. 495 TEST_P(RawPacketTest, SetSocketSendBuf) { 496 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 497 498 int max = 0; 499 int min = 0; 500 { 501 // Discover maximum buffer size by trying to set it to a large value. 502 constexpr int kSndBufSz = 0xffffffff; 503 ASSERT_THAT( 504 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &kSndBufSz, sizeof(kSndBufSz)), 505 SyscallSucceeds()); 506 507 max = 0; 508 socklen_t max_len = sizeof(max); 509 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &max, &max_len), 510 SyscallSucceeds()); 511 } 512 513 { 514 // Discover minimum buffer size by trying to set it to zero. 515 constexpr int kSndBufSz = 0; 516 ASSERT_THAT( 517 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &kSndBufSz, sizeof(kSndBufSz)), 518 SyscallSucceeds()); 519 520 socklen_t min_len = sizeof(min); 521 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &min, &min_len), 522 SyscallSucceeds()); 523 } 524 525 const int quarter_sz = min + (max - min) / 4; 526 ASSERT_THAT( 527 setsockopt(s_, SOL_SOCKET, SO_SNDBUF, &quarter_sz, sizeof(quarter_sz)), 528 SyscallSucceeds()); 529 530 int val = 0; 531 socklen_t val_len = sizeof(val); 532 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_SNDBUF, &val, &val_len), 533 SyscallSucceeds()); 534 535 #ifndef __Fuchsia__ 536 ASSERT_EQ(val, quarter_sz * 2); 537 #else 538 ASSERT_THAT(val, AnyOf(quarter_sz, quarter_sz * 2)); 539 #endif // __Fuchsia__ 540 } 541 542 TEST_P(RawPacketTest, GetSocketError) { 543 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 544 545 int val = 0; 546 socklen_t val_len = sizeof(val); 547 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_ERROR, &val, &val_len), 548 SyscallSucceeds()); 549 ASSERT_EQ(val, 0); 550 } 551 552 TEST_P(RawPacketTest, GetSocketErrorBind) { 553 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 554 555 { 556 // Bind to the loopback device. 557 struct sockaddr_ll bind_addr = {}; 558 bind_addr.sll_family = AF_PACKET; 559 bind_addr.sll_protocol = htons(GetParam()); 560 bind_addr.sll_ifindex = GetLoopbackIndex(); 561 562 ASSERT_THAT(bind(s_, reinterpret_cast<struct sockaddr*>(&bind_addr), 563 sizeof(bind_addr)), 564 SyscallSucceeds()); 565 566 // SO_ERROR should return no errors. 567 int val = 0; 568 socklen_t val_len = sizeof(val); 569 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_ERROR, &val, &val_len), 570 SyscallSucceeds()); 571 ASSERT_EQ(val, 0); 572 } 573 574 { 575 // Now try binding to an invalid interface. 576 struct sockaddr_ll bind_addr = {}; 577 bind_addr.sll_family = AF_PACKET; 578 bind_addr.sll_protocol = htons(GetParam()); 579 bind_addr.sll_ifindex = 0xffff; // Just pick a really large number. 580 581 // Binding should fail with EINVAL 582 ASSERT_THAT(bind(s_, reinterpret_cast<struct sockaddr*>(&bind_addr), 583 sizeof(bind_addr)), 584 SyscallFailsWithErrno(ENODEV)); 585 586 // SO_ERROR does not return error when the device is invalid. 587 // On Linux there is just one odd ball condition where this can return 588 // an error where the device was valid and then removed or disabled 589 // between the first check for index and the actual registration of 590 // the packet endpoint. On Netstack this is not possible as the stack 591 // global mutex is held during registration and check. 592 int val = 0; 593 socklen_t val_len = sizeof(val); 594 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_ERROR, &val, &val_len), 595 SyscallSucceeds()); 596 ASSERT_EQ(val, 0); 597 } 598 } 599 600 TEST_P(RawPacketTest, SetSocketDetachFilterNoInstalledFilter) { 601 // TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER. 602 // 603 // gVisor returns no error on SO_DETACH_FILTER even if there is no filter 604 // attached unlike linux which does return ENOENT in such cases. This is 605 // because gVisor doesn't support SO_ATTACH_FILTER and just silently returns 606 // success. 607 if (IsRunningOnGvisor()) { 608 constexpr int val = 0; 609 ASSERT_THAT(setsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)), 610 SyscallSucceeds()); 611 return; 612 } 613 constexpr int val = 0; 614 ASSERT_THAT(setsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)), 615 SyscallFailsWithErrno(ENOENT)); 616 } 617 618 TEST_P(RawPacketTest, GetSocketDetachFilter) { 619 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 620 621 int val = 0; 622 socklen_t val_len = sizeof(val); 623 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, &val_len), 624 SyscallFailsWithErrno(ENOPROTOOPT)); 625 } 626 627 TEST_P(RawPacketTest, SetAndGetSocketLinger) { 628 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 629 630 int level = SOL_SOCKET; 631 int type = SO_LINGER; 632 633 struct linger sl; 634 sl.l_onoff = 1; 635 sl.l_linger = 5; 636 ASSERT_THAT(setsockopt(s_, level, type, &sl, sizeof(sl)), 637 SyscallSucceedsWithValue(0)); 638 639 struct linger got_linger = {}; 640 socklen_t length = sizeof(sl); 641 ASSERT_THAT(getsockopt(s_, level, type, &got_linger, &length), 642 SyscallSucceedsWithValue(0)); 643 644 ASSERT_EQ(length, sizeof(got_linger)); 645 EXPECT_EQ(0, memcmp(&sl, &got_linger, length)); 646 } 647 648 TEST_P(RawPacketTest, GetSocketAcceptConn) { 649 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 650 651 int got = -1; 652 socklen_t length = sizeof(got); 653 ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_ACCEPTCONN, &got, &length), 654 SyscallSucceedsWithValue(0)); 655 656 ASSERT_EQ(length, sizeof(got)); 657 EXPECT_EQ(got, 0); 658 } 659 INSTANTIATE_TEST_SUITE_P(AllInetTests, RawPacketTest, 660 ::testing::Values(ETH_P_IP, ETH_P_ALL)); 661 662 class RawPacketMsgSizeTest : public ::testing::TestWithParam<TestAddress> {}; 663 664 TEST_P(RawPacketMsgSizeTest, SendTooLong) { 665 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 666 667 TestAddress addr = GetParam().WithPort(kPort); 668 669 FileDescriptor udp_sock = 670 ASSERT_NO_ERRNO_AND_VALUE(Socket(addr.family(), SOCK_RAW, IPPROTO_UDP)); 671 672 ASSERT_THAT( 673 connect(udp_sock.get(), reinterpret_cast<struct sockaddr*>(&addr.addr), 674 addr.addr_len), 675 SyscallSucceeds()); 676 677 const char buf[65536] = {}; 678 ASSERT_THAT(send(udp_sock.get(), buf, sizeof(buf), 0), 679 SyscallFailsWithErrno(EMSGSIZE)); 680 } 681 682 // TODO(https://fxbug.dev/42156918): Run this test on Fuchsia once splice is 683 // available. 684 #ifndef __Fuchsia__ 685 TEST_P(RawPacketMsgSizeTest, SpliceTooLong) { 686 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HavePacketSocketCapability())); 687 688 const char buf[65536] = {}; 689 int fds[2]; 690 ASSERT_THAT(pipe(fds), SyscallSucceeds()); 691 ASSERT_THAT(write(fds[1], buf, sizeof(buf)), 692 SyscallSucceedsWithValue(sizeof(buf))); 693 694 TestAddress addr = GetParam().WithPort(kPort); 695 696 FileDescriptor udp_sock = 697 ASSERT_NO_ERRNO_AND_VALUE(Socket(addr.family(), SOCK_RAW, IPPROTO_UDP)); 698 699 ASSERT_THAT( 700 connect(udp_sock.get(), reinterpret_cast<struct sockaddr*>(&addr.addr), 701 addr.addr_len), 702 SyscallSucceeds()); 703 704 ssize_t n = splice(fds[0], nullptr, udp_sock.get(), nullptr, sizeof(buf), 0); 705 if (IsRunningOnGvisor()) { 706 EXPECT_THAT(n, SyscallFailsWithErrno(EMSGSIZE)); 707 } else { 708 // TODO(gvisor.dev/issue/138): Linux sends out multiple UDP datagrams, each 709 // of the size of a page. 710 EXPECT_THAT(n, SyscallSucceedsWithValue(sizeof(buf))); 711 } 712 } 713 #endif // __Fuchsia__ 714 715 INSTANTIATE_TEST_SUITE_P(AllRawPacketMsgSizeTest, RawPacketMsgSizeTest, 716 ::testing::Values(V4Loopback(), V6Loopback())); 717 718 } // namespace 719 720 } // namespace testing 721 } // namespace gvisor