From 35ea47c6fc85a90d6507b8fad1a515dbcd7e3d88 Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Fri, 20 May 2022 13:39:36 -0700 Subject: [PATCH] Add test for SO_REUSEPORT and SO_BINDTODEVICE together Check that when two sockets are bound to the same device and have SO_REUSEPORT set, they can both be bound to the same address. This test provides missing coverage for when the two socket options are set together. Bug: https://fxbug.dev/97822 PiperOrigin-RevId: 450053747 --- test/syscalls/linux/socket_inet_loopback.cc | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/syscalls/linux/socket_inet_loopback.cc b/test/syscalls/linux/socket_inet_loopback.cc index 0ba88735f..e7a3cac62 100644 --- a/test/syscalls/linux/socket_inet_loopback.cc +++ b/test/syscalls/linux/socket_inet_loopback.cc @@ -2471,6 +2471,45 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, PortReuseTwoSockets) { } } +TEST_P(SocketMultiProtocolInetLoopbackTest, BindToDeviceReusePort) { + ProtocolTestParam const& param = GetParam(); + TestAddress const& test_addr = V4Loopback(); + + auto socket1 = + ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); + auto socket2 = + ASSERT_NO_ERRNO_AND_VALUE(Socket(test_addr.family(), param.type, 0)); + + const char kLoopbackDeviceName[] = "lo"; + + // Bind socket1 with REUSEPORT and BINDTODEVICE. + ASSERT_THAT(setsockopt(socket1.get(), SOL_SOCKET, SO_REUSEPORT, &kSockOptOn, + sizeof(kSockOptOn)), + SyscallSucceeds()); + ASSERT_THAT(setsockopt(socket1.get(), SOL_SOCKET, SO_BINDTODEVICE, + kLoopbackDeviceName, strlen(kLoopbackDeviceName)), + SyscallSucceeds()); + + // Bind the first socket to the loopback and take note of the selected port. + auto addr = V4Loopback(); + ASSERT_THAT(bind(socket1.get(), AsSockAddr(&addr.addr), addr.addr_len), + SyscallSucceeds()); + socklen_t addr_len = addr.addr_len; + ASSERT_THAT(getsockname(socket1.get(), AsSockAddr(&addr.addr), &addr_len), + SyscallSucceeds()); + EXPECT_EQ(addr_len, addr.addr_len); + + // Bind socket2 to the same device and address as socket1. + ASSERT_THAT(setsockopt(socket2.get(), SOL_SOCKET, SO_BINDTODEVICE, + kLoopbackDeviceName, strlen(kLoopbackDeviceName)), + SyscallSucceeds()); + ASSERT_THAT(setsockopt(socket2.get(), SOL_SOCKET, SO_REUSEPORT, &kSockOptOn, + sizeof(kSockOptOn)), + SyscallSucceeds()); + ASSERT_THAT(bind(socket2.get(), AsSockAddr(&addr.addr), addr.addr_len), + SyscallSucceeds()); +} + // Check that when a socket was bound to an address with REUSEPORT and then // closed, we can bind a different socket to the same address without needing // REUSEPORT.