gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_ip_unbound.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 <netinet/in.h> 17 #include <sys/socket.h> 18 #include <sys/types.h> 19 #include <sys/un.h> 20 21 #include <cstdio> 22 #include <cstring> 23 24 #include "gmock/gmock.h" 25 #include "gtest/gtest.h" 26 #include "test/syscalls/linux/ip_socket_test_util.h" 27 #include "test/util/socket_util.h" 28 #include "test/util/test_util.h" 29 30 namespace gvisor { 31 namespace testing { 32 33 // Test fixture for tests that apply to pairs of IP sockets. 34 using IPUnboundSocketTest = SimpleSocketTest; 35 36 TEST_P(IPUnboundSocketTest, TtlDefault) { 37 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 38 39 int get = -1; 40 socklen_t get_sz = sizeof(get); 41 EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get, &get_sz), 42 SyscallSucceedsWithValue(0)); 43 EXPECT_TRUE(get == 64 || get == 127); 44 EXPECT_EQ(get_sz, sizeof(get)); 45 } 46 47 TEST_P(IPUnboundSocketTest, SetTtl) { 48 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 49 50 int get1 = -1; 51 socklen_t get1_sz = sizeof(get1); 52 EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get1, &get1_sz), 53 SyscallSucceedsWithValue(0)); 54 EXPECT_EQ(get1_sz, sizeof(get1)); 55 56 int set = 100; 57 if (set == get1) { 58 set += 1; 59 } 60 socklen_t set_sz = sizeof(set); 61 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz), 62 SyscallSucceedsWithValue(0)); 63 64 int get2 = -1; 65 socklen_t get2_sz = sizeof(get2); 66 EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get2, &get2_sz), 67 SyscallSucceedsWithValue(0)); 68 EXPECT_EQ(get2_sz, sizeof(get2)); 69 EXPECT_EQ(get2, set); 70 } 71 72 TEST_P(IPUnboundSocketTest, ResetTtlToDefault) { 73 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 74 75 int get1 = -1; 76 socklen_t get1_sz = sizeof(get1); 77 EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get1, &get1_sz), 78 SyscallSucceedsWithValue(0)); 79 EXPECT_EQ(get1_sz, sizeof(get1)); 80 81 int set1 = 100; 82 if (set1 == get1) { 83 set1 += 1; 84 } 85 socklen_t set1_sz = sizeof(set1); 86 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set1, set1_sz), 87 SyscallSucceedsWithValue(0)); 88 89 int set2 = -1; 90 socklen_t set2_sz = sizeof(set2); 91 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set2, set2_sz), 92 SyscallSucceedsWithValue(0)); 93 94 int get2 = -1; 95 socklen_t get2_sz = sizeof(get2); 96 EXPECT_THAT(getsockopt(socket->get(), IPPROTO_IP, IP_TTL, &get2, &get2_sz), 97 SyscallSucceedsWithValue(0)); 98 EXPECT_EQ(get2_sz, sizeof(get2)); 99 EXPECT_TRUE(get2 == 64 || get2 == 127); 100 EXPECT_EQ(get2, get1); 101 } 102 103 TEST_P(IPUnboundSocketTest, ZeroTtl) { 104 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 105 106 int set = 0; 107 socklen_t set_sz = sizeof(set); 108 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz), 109 SyscallFailsWithErrno(EINVAL)); 110 } 111 112 TEST_P(IPUnboundSocketTest, InvalidLargeTtl) { 113 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 114 115 int set = 256; 116 socklen_t set_sz = sizeof(set); 117 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz), 118 SyscallFailsWithErrno(EINVAL)); 119 } 120 121 TEST_P(IPUnboundSocketTest, InvalidNegativeTtl) { 122 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 123 124 int set = -2; 125 socklen_t set_sz = sizeof(set); 126 EXPECT_THAT(setsockopt(socket->get(), IPPROTO_IP, IP_TTL, &set, set_sz), 127 SyscallFailsWithErrno(EINVAL)); 128 } 129 130 struct TOSOption { 131 int level; 132 int option; 133 int cmsg_level; 134 }; 135 136 constexpr int INET_ECN_MASK = 3; 137 138 static TOSOption GetTOSOption(int domain) { 139 TOSOption opt; 140 switch (domain) { 141 case AF_INET: 142 opt.level = IPPROTO_IP; 143 opt.option = IP_TOS; 144 opt.cmsg_level = SOL_IP; 145 break; 146 case AF_INET6: 147 opt.level = IPPROTO_IPV6; 148 opt.option = IPV6_TCLASS; 149 opt.cmsg_level = SOL_IPV6; 150 break; 151 } 152 return opt; 153 } 154 155 TEST_P(IPUnboundSocketTest, TOSDefault) { 156 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 157 TOSOption t = GetTOSOption(GetParam().domain); 158 int get = -1; 159 socklen_t get_sz = sizeof(get); 160 constexpr int kDefaultTOS = 0; 161 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 162 SyscallSucceedsWithValue(0)); 163 EXPECT_EQ(get_sz, sizeof(get)); 164 EXPECT_EQ(get, kDefaultTOS); 165 } 166 167 TEST_P(IPUnboundSocketTest, SetTOS) { 168 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 169 int set = 0xC0; 170 socklen_t set_sz = sizeof(set); 171 TOSOption t = GetTOSOption(GetParam().domain); 172 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 173 SyscallSucceedsWithValue(0)); 174 175 int get = -1; 176 socklen_t get_sz = sizeof(get); 177 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 178 SyscallSucceedsWithValue(0)); 179 EXPECT_EQ(get_sz, sizeof(get)); 180 EXPECT_EQ(get, set); 181 } 182 183 TEST_P(IPUnboundSocketTest, ZeroTOS) { 184 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 185 int set = 0; 186 socklen_t set_sz = sizeof(set); 187 TOSOption t = GetTOSOption(GetParam().domain); 188 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 189 SyscallSucceedsWithValue(0)); 190 int get = -1; 191 socklen_t get_sz = sizeof(get); 192 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 193 SyscallSucceedsWithValue(0)); 194 EXPECT_EQ(get_sz, sizeof(get)); 195 EXPECT_EQ(get, set); 196 } 197 198 TEST_P(IPUnboundSocketTest, InvalidLargeTOS) { 199 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 200 // Test with exceeding the byte space. 201 int set = 256; 202 constexpr int kDefaultTOS = 0; 203 socklen_t set_sz = sizeof(set); 204 TOSOption t = GetTOSOption(GetParam().domain); 205 if (GetParam().domain == AF_INET) { 206 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 207 SyscallSucceedsWithValue(0)); 208 } else { 209 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 210 SyscallFailsWithErrno(EINVAL)); 211 } 212 int get = -1; 213 socklen_t get_sz = sizeof(get); 214 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 215 SyscallSucceedsWithValue(0)); 216 EXPECT_EQ(get_sz, sizeof(get)); 217 EXPECT_EQ(get, kDefaultTOS); 218 } 219 220 TEST_P(IPUnboundSocketTest, CheckSkipECN) { 221 // Test is inconsistant on different kernels. 222 SKIP_IF(!IsRunningOnGvisor() || IsRunningWithHostinet()); 223 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 224 int set = 0xFF; 225 socklen_t set_sz = sizeof(set); 226 TOSOption t = GetTOSOption(GetParam().domain); 227 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 228 SyscallSucceedsWithValue(0)); 229 int expect = static_cast<uint8_t>(set); 230 if (GetParam().protocol == IPPROTO_TCP) { 231 expect &= ~INET_ECN_MASK; 232 } 233 int get = -1; 234 socklen_t get_sz = sizeof(get); 235 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 236 SyscallSucceedsWithValue(0)); 237 EXPECT_EQ(get_sz, sizeof(get)); 238 EXPECT_EQ(get, expect); 239 } 240 241 TEST_P(IPUnboundSocketTest, ZeroTOSOptionSize) { 242 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 243 int set = 0xC0; 244 socklen_t set_sz = 0; 245 TOSOption t = GetTOSOption(GetParam().domain); 246 if (GetParam().domain == AF_INET) { 247 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 248 SyscallSucceedsWithValue(0)); 249 } else { 250 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 251 SyscallFailsWithErrno(EINVAL)); 252 } 253 int get = -1; 254 socklen_t get_sz = 0; 255 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 256 SyscallSucceedsWithValue(0)); 257 EXPECT_EQ(get_sz, 0); 258 EXPECT_EQ(get, -1); 259 } 260 261 TEST_P(IPUnboundSocketTest, SmallTOSOptionSize) { 262 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 263 int set = 0xC0; 264 constexpr int kDefaultTOS = 0; 265 TOSOption t = GetTOSOption(GetParam().domain); 266 for (socklen_t i = 1; i < sizeof(int); i++) { 267 int expect_tos; 268 socklen_t expect_sz; 269 if (GetParam().domain == AF_INET) { 270 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i), 271 SyscallSucceedsWithValue(0)); 272 expect_tos = set; 273 expect_sz = sizeof(uint8_t); 274 } else { 275 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i), 276 SyscallFailsWithErrno(EINVAL)); 277 expect_tos = kDefaultTOS; 278 expect_sz = i; 279 } 280 uint get = -1; 281 socklen_t get_sz = i; 282 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 283 SyscallSucceedsWithValue(0)); 284 EXPECT_EQ(get_sz, expect_sz); 285 // Account for partial copies by getsockopt, retrieve the lower 286 // bits specified by get_sz, while comparing against expect_tos. 287 EXPECT_EQ(get & ~(~static_cast<uint>(0) << (get_sz * 8)), expect_tos); 288 } 289 } 290 291 TEST_P(IPUnboundSocketTest, LargeTOSOptionSize) { 292 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 293 int set = 0xC0; 294 TOSOption t = GetTOSOption(GetParam().domain); 295 for (socklen_t i = sizeof(int); i < 10; i++) { 296 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i), 297 SyscallSucceedsWithValue(0)); 298 int get = -1; 299 socklen_t get_sz = i; 300 // We expect the system call handler to only copy atmost sizeof(int) bytes 301 // as asserted by the check below. Hence, we do not expect the copy to 302 // overflow in getsockopt. 303 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 304 SyscallSucceedsWithValue(0)); 305 EXPECT_EQ(get_sz, sizeof(int)); 306 EXPECT_EQ(get, set); 307 } 308 } 309 310 TEST_P(IPUnboundSocketTest, NegativeTOS) { 311 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 312 313 int set = -1; 314 socklen_t set_sz = sizeof(set); 315 TOSOption t = GetTOSOption(GetParam().domain); 316 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 317 SyscallSucceedsWithValue(0)); 318 int expect; 319 if (GetParam().domain == AF_INET) { 320 expect = static_cast<uint8_t>(set); 321 if (GetParam().protocol == IPPROTO_TCP) { 322 expect &= ~INET_ECN_MASK; 323 } 324 } else { 325 // On IPv6 TCLASS, setting -1 has the effect of resetting the 326 // TrafficClass. 327 expect = 0; 328 } 329 int get = -1; 330 socklen_t get_sz = sizeof(get); 331 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 332 SyscallSucceedsWithValue(0)); 333 EXPECT_EQ(get_sz, sizeof(get)); 334 EXPECT_EQ(get, expect); 335 } 336 337 TEST_P(IPUnboundSocketTest, InvalidNegativeTOS) { 338 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 339 int set = -2; 340 socklen_t set_sz = sizeof(set); 341 TOSOption t = GetTOSOption(GetParam().domain); 342 int expect; 343 if (GetParam().domain == AF_INET) { 344 ASSERT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 345 SyscallSucceedsWithValue(0)); 346 expect = static_cast<uint8_t>(set); 347 if (GetParam().protocol == IPPROTO_TCP) { 348 expect &= ~INET_ECN_MASK; 349 } 350 } else { 351 ASSERT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), 352 SyscallFailsWithErrno(EINVAL)); 353 expect = 0; 354 } 355 int get = 0; 356 socklen_t get_sz = sizeof(get); 357 ASSERT_THAT(getsockopt(socket->get(), t.level, t.option, &get, &get_sz), 358 SyscallSucceedsWithValue(0)); 359 EXPECT_EQ(get_sz, sizeof(get)); 360 EXPECT_EQ(get, expect); 361 } 362 363 TEST_P(IPUnboundSocketTest, NullTOS) { 364 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 365 TOSOption t = GetTOSOption(GetParam().domain); 366 int set_sz = sizeof(int); 367 if (GetParam().domain == AF_INET) { 368 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, nullptr, set_sz), 369 SyscallFailsWithErrno(EFAULT)); 370 } else { // AF_INET6 371 // The AF_INET6 behavior is not yet compatible. gVisor will try to read 372 // optval from user memory at syscall handler, it needs substantial 373 // refactoring to implement this behavior just for IPv6. 374 if (IsRunningOnGvisor()) { 375 EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, nullptr, set_sz), 376 SyscallFailsWithErrno(EFAULT)); 377 } else { 378 // Linux's IPv6 stack treats nullptr optval as input of 0, so the call 379 // succeeds. (net/ipv6/ipv6_sockglue.c, do_ipv6_setsockopt()) 380 // 381 // Linux's implementation would need fixing as passing a nullptr as optval 382 // and non-zero optlen may not be valid. 383 // TODO(b/158666797): Combine the gVisor and linux cases for IPv6. 384 // Some kernel versions return EFAULT, so we handle both. 385 EXPECT_THAT( 386 setsockopt(socket->get(), t.level, t.option, nullptr, set_sz), 387 AnyOf(SyscallFailsWithErrno(EFAULT), SyscallSucceedsWithValue(0))); 388 } 389 } 390 socklen_t get_sz = sizeof(int); 391 EXPECT_THAT(getsockopt(socket->get(), t.level, t.option, nullptr, &get_sz), 392 SyscallFailsWithErrno(EFAULT)); 393 int get = -1; 394 EXPECT_THAT(getsockopt(socket->get(), t.level, t.option, &get, nullptr), 395 SyscallFailsWithErrno(EFAULT)); 396 } 397 398 TEST_P(IPUnboundSocketTest, InsufficientBufferTOS) { 399 SKIP_IF(GetParam().protocol == IPPROTO_TCP); 400 401 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 402 TOSOption t = GetTOSOption(GetParam().domain); 403 404 in_addr addr4; 405 in6_addr addr6; 406 ASSERT_THAT(inet_pton(AF_INET, "127.0.0.1", &addr4), ::testing::Eq(1)); 407 ASSERT_THAT(inet_pton(AF_INET6, "fe80::", &addr6), ::testing::Eq(1)); 408 409 cmsghdr cmsg = {}; 410 cmsg.cmsg_len = sizeof(cmsg); 411 cmsg.cmsg_level = t.cmsg_level; 412 cmsg.cmsg_type = t.option; 413 414 msghdr msg = {}; 415 msg.msg_control = &cmsg; 416 msg.msg_controllen = sizeof(cmsg); 417 if (GetParam().domain == AF_INET) { 418 msg.msg_name = &addr4; 419 msg.msg_namelen = sizeof(addr4); 420 } else { 421 msg.msg_name = &addr6; 422 msg.msg_namelen = sizeof(addr6); 423 } 424 425 EXPECT_THAT(sendmsg(socket->get(), &msg, 0), SyscallFailsWithErrno(EINVAL)); 426 } 427 428 TEST_P(IPUnboundSocketTest, ReuseAddrDefault) { 429 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 430 431 int get = -1; 432 socklen_t get_sz = sizeof(get); 433 ASSERT_THAT( 434 getsockopt(socket->get(), SOL_SOCKET, SO_REUSEADDR, &get, &get_sz), 435 SyscallSucceedsWithValue(0)); 436 EXPECT_EQ(get, kSockOptOff); 437 EXPECT_EQ(get_sz, sizeof(get)); 438 } 439 440 TEST_P(IPUnboundSocketTest, SetReuseAddr) { 441 auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket()); 442 443 ASSERT_THAT(setsockopt(socket->get(), SOL_SOCKET, SO_REUSEADDR, &kSockOptOn, 444 sizeof(kSockOptOn)), 445 SyscallSucceedsWithValue(0)); 446 447 int get = -1; 448 socklen_t get_sz = sizeof(get); 449 ASSERT_THAT( 450 getsockopt(socket->get(), SOL_SOCKET, SO_REUSEADDR, &get, &get_sz), 451 SyscallSucceedsWithValue(0)); 452 EXPECT_EQ(get, kSockOptOn); 453 EXPECT_EQ(get_sz, sizeof(get)); 454 } 455 456 INSTANTIATE_TEST_SUITE_P( 457 IPUnboundSockets, IPUnboundSocketTest, 458 ::testing::ValuesIn(VecCat<SocketKind>( 459 ApplyVec<SocketKind>(IPv4UDPUnboundSocket, 460 std::vector<int>{0, SOCK_NONBLOCK}), 461 ApplyVec<SocketKind>(IPv6UDPUnboundSocket, 462 std::vector<int>{0, SOCK_NONBLOCK}), 463 ApplyVec<SocketKind>(IPv4TCPUnboundSocket, 464 std::vector{0, SOCK_NONBLOCK}), 465 ApplyVec<SocketKind>(IPv6TCPUnboundSocket, 466 std::vector{0, SOCK_NONBLOCK})))); 467 468 } // namespace testing 469 } // namespace gvisor