gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/raw_socket_hdrincl.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 <netinet/in.h> 16 #include <netinet/ip.h> 17 #include <netinet/ip_icmp.h> 18 #include <netinet/udp.h> 19 #include <poll.h> 20 #include <sys/socket.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include <algorithm> 25 #include <cstring> 26 27 #include "gtest/gtest.h" 28 #include "absl/base/internal/endian.h" 29 #include "test/syscalls/linux/unix_domain_socket_test_util.h" 30 #include "test/util/capability_util.h" 31 #include "test/util/file_descriptor.h" 32 #include "test/util/socket_util.h" 33 #include "test/util/test_util.h" 34 35 namespace gvisor { 36 namespace testing { 37 38 namespace { 39 40 // Tests for IPPROTO_RAW raw sockets, which implies IP_HDRINCL. 41 class RawHDRINCL : public ::testing::Test { 42 protected: 43 // Creates a socket to be used in tests. 44 void SetUp() override; 45 46 // Closes the socket created by SetUp(). 47 void TearDown() override; 48 49 // Returns a valid looback IP header with no payload. 50 struct iphdr LoopbackHeader(); 51 52 // Fills in buf with an IP header, UDP header, and payload. Returns false if 53 // buf_size isn't large enough to hold everything. 54 bool FillPacket(char* buf, size_t buf_size, int port, const char* payload, 55 uint16_t payload_size); 56 57 // The socket used for both reading and writing. 58 int socket_; 59 60 // The loopback address. 61 struct sockaddr_in addr_; 62 }; 63 64 void RawHDRINCL::SetUp() { 65 if (!ASSERT_NO_ERRNO_AND_VALUE(HaveRawIPSocketCapability())) { 66 ASSERT_THAT(socket(AF_INET, SOCK_RAW, IPPROTO_RAW), 67 SyscallFailsWithErrno(EPERM)); 68 GTEST_SKIP(); 69 } 70 71 ASSERT_THAT(socket_ = socket(AF_INET, SOCK_RAW, IPPROTO_RAW), 72 SyscallSucceeds()); 73 74 addr_ = {}; 75 76 addr_.sin_port = IPPROTO_IP; 77 addr_.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 78 addr_.sin_family = AF_INET; 79 } 80 81 void RawHDRINCL::TearDown() { 82 // TearDown will be run even if we skip the test. 83 if (ASSERT_NO_ERRNO_AND_VALUE(HaveRawIPSocketCapability())) { 84 EXPECT_THAT(close(socket_), SyscallSucceeds()); 85 } 86 } 87 88 struct iphdr RawHDRINCL::LoopbackHeader() { 89 struct iphdr hdr = {}; 90 hdr.ihl = 5; 91 hdr.version = 4; 92 hdr.tos = 0; 93 hdr.tot_len = absl::gbswap_16(sizeof(hdr)); 94 hdr.id = 0; 95 hdr.frag_off = 0; 96 hdr.ttl = 7; 97 hdr.protocol = 1; 98 hdr.daddr = htonl(INADDR_LOOPBACK); 99 // hdr.check is set by the network stack. 100 // hdr.tot_len is set by the network stack. 101 // hdr.saddr is set by the network stack. 102 return hdr; 103 } 104 105 bool RawHDRINCL::FillPacket(char* buf, size_t buf_size, int port, 106 const char* payload, uint16_t payload_size) { 107 if (buf_size < sizeof(struct iphdr) + sizeof(struct udphdr) + payload_size) { 108 return false; 109 } 110 111 struct iphdr ip = LoopbackHeader(); 112 ip.protocol = IPPROTO_UDP; 113 114 struct udphdr udp = {}; 115 udp.source = absl::gbswap_16(port); 116 udp.dest = absl::gbswap_16(port); 117 udp.len = absl::gbswap_16(sizeof(udp) + payload_size); 118 udp.check = 0; 119 120 memcpy(buf, reinterpret_cast<char*>(&ip), sizeof(ip)); 121 memcpy(buf + sizeof(ip), reinterpret_cast<char*>(&udp), sizeof(udp)); 122 memcpy(buf + sizeof(ip) + sizeof(udp), payload, payload_size); 123 124 return true; 125 } 126 127 // We should be able to create multiple IPPROTO_RAW sockets. RawHDRINCL::Setup 128 // creates the first one, so we only have to create one more here. 129 TEST_F(RawHDRINCL, MultipleCreation) { 130 int s2; 131 ASSERT_THAT(s2 = socket(AF_INET, SOCK_RAW, IPPROTO_RAW), SyscallSucceeds()); 132 133 ASSERT_THAT(close(s2), SyscallSucceeds()); 134 } 135 136 // Test that shutting down an unconnected socket fails. 137 TEST_F(RawHDRINCL, FailShutdownWithoutConnect) { 138 ASSERT_THAT(shutdown(socket_, SHUT_WR), SyscallFailsWithErrno(ENOTCONN)); 139 ASSERT_THAT(shutdown(socket_, SHUT_RD), SyscallFailsWithErrno(ENOTCONN)); 140 } 141 142 // Test that listen() fails. 143 TEST_F(RawHDRINCL, FailListen) { 144 ASSERT_THAT(listen(socket_, 1), SyscallFailsWithErrno(ENOTSUP)); 145 } 146 147 // Test that accept() fails. 148 TEST_F(RawHDRINCL, FailAccept) { 149 struct sockaddr saddr; 150 socklen_t addrlen; 151 ASSERT_THAT(accept(socket_, &saddr, &addrlen), 152 SyscallFailsWithErrno(ENOTSUP)); 153 } 154 155 // Test that the socket is writable immediately. 156 TEST_F(RawHDRINCL, PollWritableImmediately) { 157 struct pollfd pfd = {}; 158 pfd.fd = socket_; 159 pfd.events = POLLOUT; 160 ASSERT_THAT(RetryEINTR(poll)(&pfd, 1, 0), SyscallSucceedsWithValue(1)); 161 } 162 163 // Test that the socket isn't readable. 164 TEST_F(RawHDRINCL, NotReadable) { 165 // Try to receive data with MSG_DONTWAIT, which returns immediately if there's 166 // nothing to be read. 167 char buf[117]; 168 ASSERT_THAT(RetryEINTR(recv)(socket_, buf, sizeof(buf), MSG_DONTWAIT), 169 SyscallFailsWithErrno(EAGAIN)); 170 } 171 172 // Test that we can connect() to a valid IP (loopback). 173 TEST_F(RawHDRINCL, ConnectToLoopback) { 174 ASSERT_THAT(connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_), 175 sizeof(addr_)), 176 SyscallSucceeds()); 177 } 178 179 TEST_F(RawHDRINCL, SendWithoutConnectFails) { 180 struct iphdr hdr = LoopbackHeader(); 181 ASSERT_THAT(send(socket_, &hdr, sizeof(hdr), 0), 182 SyscallFailsWithErrno(EDESTADDRREQ)); 183 } 184 185 // HDRINCL implies write-only. Verify that we can't read a packet sent to 186 // loopback. 187 TEST_F(RawHDRINCL, NotReadableAfterWrite) { 188 ASSERT_THAT(connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_), 189 sizeof(addr_)), 190 SyscallSucceeds()); 191 192 // Construct a packet with an IP header, UDP header, and payload. 193 constexpr char kPayload[] = "odst"; 194 char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)]; 195 ASSERT_TRUE(FillPacket(packet, sizeof(packet), 40000 /* port */, kPayload, 196 sizeof(kPayload))); 197 198 socklen_t addrlen = sizeof(addr_); 199 ASSERT_NO_FATAL_FAILURE( 200 sendto(socket_, reinterpret_cast<void*>(&packet), sizeof(packet), 0, 201 reinterpret_cast<struct sockaddr*>(&addr_), addrlen)); 202 203 struct pollfd pfd = {}; 204 pfd.fd = socket_; 205 pfd.events = POLLIN; 206 ASSERT_THAT(RetryEINTR(poll)(&pfd, 1, 1000), SyscallSucceedsWithValue(0)); 207 } 208 209 TEST_F(RawHDRINCL, WriteTooSmall) { 210 ASSERT_THAT(connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_), 211 sizeof(addr_)), 212 SyscallSucceeds()); 213 214 // This is smaller than the size of an IP header. 215 constexpr char kBuf[] = "JP5"; 216 ASSERT_THAT(send(socket_, kBuf, sizeof(kBuf), 0), 217 SyscallFailsWithErrno(EINVAL)); 218 } 219 220 // Bind to localhost. 221 TEST_F(RawHDRINCL, BindToLocalhost) { 222 ASSERT_THAT( 223 bind(socket_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)), 224 SyscallSucceeds()); 225 } 226 227 // Bind to a different address. 228 TEST_F(RawHDRINCL, BindToInvalid) { 229 struct sockaddr_in bind_addr = {}; 230 bind_addr.sin_family = AF_INET; 231 bind_addr.sin_addr = {1}; // 1.0.0.0 - An address that we can't bind to. 232 ASSERT_THAT(bind(socket_, reinterpret_cast<struct sockaddr*>(&bind_addr), 233 sizeof(bind_addr)), 234 SyscallFailsWithErrno(EADDRNOTAVAIL)); 235 } 236 237 // Send and receive a packet. 238 TEST_F(RawHDRINCL, SendAndReceive) { 239 int port = 40000; 240 if (!IsRunningOnGvisor()) { 241 port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE( 242 PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false))); 243 } 244 245 // IPPROTO_RAW sockets are write-only. We'll have to open another socket to 246 // read what we write. 247 FileDescriptor udp_sock = 248 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP)); 249 250 // Construct a packet with an IP header, UDP header, and payload. 251 constexpr char kPayload[] = "toto"; 252 char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)]; 253 ASSERT_TRUE( 254 FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload))); 255 256 socklen_t addrlen = sizeof(addr_); 257 ASSERT_NO_FATAL_FAILURE(sendto(socket_, &packet, sizeof(packet), 0, 258 reinterpret_cast<struct sockaddr*>(&addr_), 259 addrlen)); 260 261 // Receive the payload. 262 char recv_buf[sizeof(packet)]; 263 struct sockaddr_in src; 264 socklen_t src_size = sizeof(src); 265 ASSERT_THAT(recvfrom(udp_sock.get(), recv_buf, sizeof(recv_buf), 0, 266 reinterpret_cast<struct sockaddr*>(&src), &src_size), 267 SyscallSucceedsWithValue(sizeof(packet))); 268 EXPECT_EQ( 269 memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr), 270 sizeof(kPayload)), 271 0); 272 // The network stack should have set the source address. 273 EXPECT_EQ(src.sin_family, AF_INET); 274 EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK); 275 } 276 277 // Send and receive a packet where the sendto address is not the same as the 278 // provided destination. 279 TEST_F(RawHDRINCL, SendAndReceiveDifferentAddress) { 280 int port = 40000; 281 if (!IsRunningOnGvisor()) { 282 port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE( 283 PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false))); 284 } 285 286 // IPPROTO_RAW sockets are write-only. We'll have to open another socket to 287 // read what we write. 288 FileDescriptor udp_sock = 289 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP)); 290 291 // Construct a packet with an IP header, UDP header, and payload. 292 constexpr char kPayload[] = "toto"; 293 char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)]; 294 ASSERT_TRUE( 295 FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload))); 296 // Overwrite the IP destination address with an IP we can't get to. 297 constexpr int32_t kUnreachable = 42; 298 struct iphdr iphdr = {}; 299 memcpy(&iphdr, packet, sizeof(iphdr)); 300 iphdr.daddr = kUnreachable; 301 memcpy(packet, &iphdr, sizeof(iphdr)); 302 303 // Send to localhost via loopback. 304 socklen_t addrlen = sizeof(addr_); 305 ASSERT_NO_FATAL_FAILURE(sendto(socket_, &packet, sizeof(packet), 0, 306 reinterpret_cast<struct sockaddr*>(&addr_), 307 addrlen)); 308 309 // Receive the payload. Despite an unreachable destination address, sendto 310 // should have sent the packet through loopback. 311 char recv_buf[sizeof(packet)]; 312 struct sockaddr_in src; 313 socklen_t src_size = sizeof(src); 314 ASSERT_THAT(recvfrom(udp_sock.get(), recv_buf, sizeof(recv_buf), 0, 315 reinterpret_cast<struct sockaddr*>(&src), &src_size), 316 SyscallSucceedsWithValue(sizeof(packet))); 317 EXPECT_EQ( 318 memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr), 319 sizeof(kPayload)), 320 0); 321 // The network stack should have set the source address. 322 EXPECT_EQ(src.sin_family, AF_INET); 323 EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK); 324 struct iphdr recv_iphdr = {}; 325 memcpy(&recv_iphdr, recv_buf, sizeof(recv_iphdr)); 326 // The destination address is kUnreachable despite arriving via loopback. 327 EXPECT_EQ(recv_iphdr.daddr, kUnreachable); 328 } 329 330 // Send and receive a packet w/ the IP_HDRINCL option set. 331 TEST_F(RawHDRINCL, SendAndReceiveIPHdrIncl) { 332 int port = 40000; 333 if (!IsRunningOnGvisor()) { 334 port = static_cast<short>(ASSERT_NO_ERRNO_AND_VALUE( 335 PortAvailable(0, AddressFamily::kIpv4, SocketType::kUdp, false))); 336 } 337 338 FileDescriptor recv_sock = 339 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP)); 340 341 FileDescriptor send_sock = 342 ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_RAW, IPPROTO_UDP)); 343 344 // Enable IP_HDRINCL option so that we can build and send w/ an IP 345 // header. 346 constexpr int kSockOptOn = 1; 347 ASSERT_THAT(setsockopt(send_sock.get(), SOL_IP, IP_HDRINCL, &kSockOptOn, 348 sizeof(kSockOptOn)), 349 SyscallSucceeds()); 350 // This is not strictly required but we do it to make sure that setting 351 // IP_HDRINCL on a non IPPROTO_RAW socket does not prevent it from receiving 352 // packets. 353 ASSERT_THAT(setsockopt(recv_sock.get(), SOL_IP, IP_HDRINCL, &kSockOptOn, 354 sizeof(kSockOptOn)), 355 SyscallSucceeds()); 356 357 // Construct a packet with an IP header, UDP header, and payload. 358 constexpr char kPayload[] = "toto"; 359 char packet[sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(kPayload)]; 360 ASSERT_TRUE( 361 FillPacket(packet, sizeof(packet), port, kPayload, sizeof(kPayload))); 362 363 socklen_t addrlen = sizeof(addr_); 364 ASSERT_NO_FATAL_FAILURE(sendto(send_sock.get(), &packet, sizeof(packet), 0, 365 reinterpret_cast<struct sockaddr*>(&addr_), 366 addrlen)); 367 368 // Receive the payload. 369 char recv_buf[sizeof(packet)]; 370 struct sockaddr_in src; 371 socklen_t src_size = sizeof(src); 372 ASSERT_THAT(recvfrom(recv_sock.get(), recv_buf, sizeof(recv_buf), 0, 373 reinterpret_cast<struct sockaddr*>(&src), &src_size), 374 SyscallSucceedsWithValue(sizeof(packet))); 375 EXPECT_EQ( 376 memcmp(kPayload, recv_buf + sizeof(struct iphdr) + sizeof(struct udphdr), 377 sizeof(kPayload)), 378 0); 379 // The network stack should have set the source address. 380 EXPECT_EQ(src.sin_family, AF_INET); 381 EXPECT_EQ(absl::gbswap_32(src.sin_addr.s_addr), INADDR_LOOPBACK); 382 struct iphdr iphdr = {}; 383 memcpy(&iphdr, recv_buf, sizeof(iphdr)); 384 385 // Also verify that the packet we just sent was not delivered to the 386 // IPPROTO_RAW socket. 387 { 388 char recv_buf[sizeof(packet)]; 389 struct sockaddr_in src; 390 socklen_t src_size = sizeof(src); 391 ASSERT_THAT(recvfrom(socket_, recv_buf, sizeof(recv_buf), MSG_DONTWAIT, 392 reinterpret_cast<struct sockaddr*>(&src), &src_size), 393 SyscallFailsWithErrno(EAGAIN)); 394 } 395 } 396 397 } // namespace 398 399 } // namespace testing 400 } // namespace gvisor