From 2739cf46284f2786ad33b545d55b8178bc46f7de Mon Sep 17 00:00:00 2001 From: Bhasker Hariharan Date: Thu, 22 Apr 2021 16:31:11 -0700 Subject: Fix AF_UNIX listen() w/ zero backlog. In https://github.com/google/gvisor/commit/f075522849fa a check to increase zero to a minimum backlog length was removed from sys_socket.go to bring it in parity with linux and then in tcp/endpoint.go we bump backlog by 1. But this broke calling listen on a AF_UNIX socket w/ a zero backlog as in linux it does allow 1 connection even with a zero backlog. This was caught by a php runtime test socket_abstract_path.phpt. PiperOrigin-RevId: 369974744 --- .../syscalls/linux/socket_unix_unbound_abstract.cc | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'test/syscalls') diff --git a/test/syscalls/linux/socket_unix_unbound_abstract.cc b/test/syscalls/linux/socket_unix_unbound_abstract.cc index 8b1762000..dd3d25450 100644 --- a/test/syscalls/linux/socket_unix_unbound_abstract.cc +++ b/test/syscalls/linux/socket_unix_unbound_abstract.cc @@ -72,6 +72,52 @@ TEST_P(UnboundAbstractUnixSocketPairTest, BindNothing) { SyscallSucceeds()); } +TEST_P(UnboundAbstractUnixSocketPairTest, ListenZeroBacklog) { + SKIP_IF((GetParam().type & SOCK_DGRAM) != 0); + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + struct sockaddr_un addr = {}; + addr.sun_family = AF_UNIX; + constexpr char kPath[] = "\x00/foo_bar"; + memcpy(addr.sun_path, kPath, sizeof(kPath)); + ASSERT_THAT(bind(sockets->first_fd(), + reinterpret_cast(&addr), sizeof(addr)), + SyscallSucceeds()); + ASSERT_THAT(listen(sockets->first_fd(), 0 /* backlog */), SyscallSucceeds()); + ASSERT_THAT(connect(sockets->second_fd(), + reinterpret_cast(&addr), sizeof(addr)), + SyscallSucceeds()); + auto sockets2 = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + { + // Set the FD to O_NONBLOCK. + int opts; + int orig_opts; + ASSERT_THAT(opts = fcntl(sockets2->first_fd(), F_GETFL), SyscallSucceeds()); + orig_opts = opts; + opts |= O_NONBLOCK; + ASSERT_THAT(fcntl(sockets2->first_fd(), F_SETFL, opts), SyscallSucceeds()); + + ASSERT_THAT( + connect(sockets2->first_fd(), reinterpret_cast(&addr), + sizeof(addr)), + SyscallFailsWithErrno(EAGAIN)); + } + { + // Set the FD to O_NONBLOCK. + int opts; + int orig_opts; + ASSERT_THAT(opts = fcntl(sockets2->second_fd(), F_GETFL), + SyscallSucceeds()); + orig_opts = opts; + opts |= O_NONBLOCK; + ASSERT_THAT(fcntl(sockets2->second_fd(), F_SETFL, opts), SyscallSucceeds()); + + ASSERT_THAT( + connect(sockets2->second_fd(), + reinterpret_cast(&addr), sizeof(addr)), + SyscallFailsWithErrno(EAGAIN)); + } +} + TEST_P(UnboundAbstractUnixSocketPairTest, GetSockNameFullLength) { auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); -- cgit v1.2.3