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