summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux
diff options
context:
space:
mode:
authorTamir Duberstein <tamird@google.com>2020-08-28 05:31:46 -0700
committerAndrei Vagin <avagin@gmail.com>2020-09-09 17:53:10 -0700
commite50be6f7bab47c271e718dabae027c9c3590e4b9 (patch)
treeb331fe76f090248d3e47405e25599e2164a2e866 /test/syscalls/linux
parentc77a532936f245b0525703eb7e72a6cdf62c00b0 (diff)
Add test demonstrating accept bug
Updates #3780. PiperOrigin-RevId: 328922573
Diffstat (limited to 'test/syscalls/linux')
-rw-r--r--test/syscalls/linux/socket_inet_loopback.cc76
1 files changed, 76 insertions, 0 deletions
diff --git a/test/syscalls/linux/socket_inet_loopback.cc b/test/syscalls/linux/socket_inet_loopback.cc
index 67893033c..425084228 100644
--- a/test/syscalls/linux/socket_inet_loopback.cc
+++ b/test/syscalls/linux/socket_inet_loopback.cc
@@ -1111,6 +1111,82 @@ TEST_P(SocketInetLoopbackTest, AcceptedInheritsTCPUserTimeout) {
EXPECT_EQ(get, kUserTimeout);
}
+TEST_P(SocketInetLoopbackTest, TCPAcceptAfterReset) {
+ auto const& param = GetParam();
+ TestAddress const& listener = param.listener;
+ TestAddress const& connector = param.connector;
+
+ // Create the listening socket.
+ const FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP));
+ sockaddr_storage listen_addr = listener.addr;
+ ASSERT_THAT(bind(listen_fd.get(), reinterpret_cast<sockaddr*>(&listen_addr),
+ listener.addr_len),
+ SyscallSucceeds());
+ ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds());
+
+ // Get the port bound by the listening socket.
+ {
+ socklen_t addrlen = listener.addr_len;
+ ASSERT_THAT(
+ getsockname(listen_fd.get(), reinterpret_cast<sockaddr*>(&listen_addr),
+ &addrlen),
+ SyscallSucceeds());
+ }
+
+ const uint16_t port =
+ ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr));
+
+ // Connect to the listening socket.
+ FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP));
+
+ sockaddr_storage conn_addr = connector.addr;
+ ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port));
+ ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(),
+ reinterpret_cast<sockaddr*>(&conn_addr),
+ connector.addr_len),
+ SyscallSucceeds());
+
+ // Trigger a RST by turning linger off and closing the socket.
+ struct linger opt = {
+ .l_onoff = 1,
+ .l_linger = 0,
+ };
+ ASSERT_THAT(
+ setsockopt(conn_fd.get(), SOL_SOCKET, SO_LINGER, &opt, sizeof(opt)),
+ SyscallSucceeds());
+ ASSERT_THAT(close(conn_fd.release()), SyscallSucceeds());
+
+ // TODO(gvisor.dev/issue/3780): Remove this.
+ if (IsRunningOnGvisor()) {
+ // Wait for the RST to be observed.
+ absl::SleepFor(absl::Milliseconds(100));
+ }
+
+ sockaddr_storage accept_addr;
+ socklen_t addrlen = sizeof(accept_addr);
+
+ // TODO(gvisor.dev/issue/3780): Remove this.
+ if (IsRunningOnGvisor()) {
+ ASSERT_THAT(accept(listen_fd.get(),
+ reinterpret_cast<sockaddr*>(&accept_addr), &addrlen),
+ SyscallFailsWithErrno(ENOTCONN));
+ return;
+ }
+
+ conn_fd = ASSERT_NO_ERRNO_AND_VALUE(Accept(
+ listen_fd.get(), reinterpret_cast<sockaddr*>(&accept_addr), &addrlen));
+ ASSERT_EQ(addrlen, listener.addr_len);
+
+ int err;
+ socklen_t optlen = sizeof(err);
+ ASSERT_THAT(getsockopt(conn_fd.get(), SOL_SOCKET, SO_ERROR, &err, &optlen),
+ SyscallSucceeds());
+ ASSERT_EQ(err, ECONNRESET);
+ ASSERT_EQ(optlen, sizeof(err));
+}
+
// TODO(gvisor.dev/issue/1688): Partially completed passive endpoints are not
// saved. Enable S/R once issue is fixed.
TEST_P(SocketInetLoopbackTest, TCPDeferAccept_NoRandomSave) {