diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index 68e58aea5..e177f8487 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -1076,13 +1076,8 @@ func getSockOptSocket(t *kernel.Task, s socket.Socket, ep commonEndpoint, family return nil, syserr.ErrInvalidArgument } - // This option is only viable for TCP endpoints. - var v bool - if socket.IsTCP(s) { - v = tcp.EndpointState(ep.State()) == tcp.StateListen - } - vP := primitive.Int32(boolToInt32(v)) - return &vP, nil + v := primitive.Int32(boolToInt32(ep.SocketOptions().GetAcceptConn())) + return &v, nil case linux.SO_RCVLOWAT: if outLen < sizeOfInt32 { diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index d5089de79..c8bdcafa4 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -645,3 +645,7 @@ func (e *connectionedEndpoint) EventUnregister(we *waiter.Entry) { fdnotifier.UpdateFD(bsFD.NotificationFD()) } } + +func (e *connectionedEndpoint) GetAcceptConn() bool { + return e.Listening() +} diff --git a/pkg/tcpip/socketops.go b/pkg/tcpip/socketops.go index a3aadb223..b8196912f 100644 --- a/pkg/tcpip/socketops.go +++ b/pkg/tcpip/socketops.go @@ -63,6 +63,10 @@ type SocketOptionsHandler interface { // changed. The handler notifies the writers if the send buffer size is // increased with setsockopt(2) for TCP endpoints. WakeupWriters() + + // GetAcceptConn returns true if the socket is a TCP socket and is in + // listening state. + GetAcceptConn() bool } // DefaultSocketOptionsHandler is an embeddable type that implements no-op @@ -112,6 +116,11 @@ func (*DefaultSocketOptionsHandler) OnSetReceiveBufferSize(v, oldSz int64) (newS return v, nil } +// GetAcceptConn implements SocketOptionsHandler.GetAcceptConn. +func (*DefaultSocketOptionsHandler) GetAcceptConn() bool { + return false +} + // StackHandler holds methods to access the stack options. These must be // implemented by the stack. type StackHandler interface { @@ -742,3 +751,8 @@ func (so *SocketOptions) SetRcvlowat(rcvlowat int32) Error { so.rcvlowat.Store(rcvlowat) return nil } + +// GetAcceptConn gets value for SO_ACCEPTCONN option. +func (so *SocketOptions) GetAcceptConn() bool { + return so.handler.GetAcceptConn() +} diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 7b0af1759..464afb6d7 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -3325,3 +3325,7 @@ func (e *endpoint) computeTCPSendBufferSize() int64 { return newSndBufSz } + +func (e *endpoint) GetAcceptConn() bool { + return EndpointState(e.State()) == StateListen +} diff --git a/test/syscalls/linux/socket_unix_stream.cc b/test/syscalls/linux/socket_unix_stream.cc index 2f3cfc3f3..7cf68bf6f 100644 --- a/test/syscalls/linux/socket_unix_stream.cc +++ b/test/syscalls/linux/socket_unix_stream.cc @@ -229,6 +229,27 @@ TEST_P(StreamUnixSocketPairTest, IncreasedSocketSendBufUnblocksWrites) { SyscallSucceeds()); } +TEST_P(StreamUnixSocketPairTest, GetAcceptConn) { + auto bound = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, 0)); + struct sockaddr_un bind_addr = + ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(true, AF_UNIX)); + ASSERT_THAT(bind(bound.get(), AsSockAddr(&bind_addr), sizeof(bind_addr)), + SyscallSucceeds()); + int opt = 0; + socklen_t opt_len = sizeof(opt); + ASSERT_THAT( + getsockopt(bound.get(), SOL_SOCKET, SO_ACCEPTCONN, &opt, &opt_len), + SyscallSucceeds()); + ASSERT_EQ(opt, 0); + ASSERT_THAT(listen(bound.get(), + /* backlog = */ 5), // NOLINT(bugprone-argument-comment) + SyscallSucceeds()); + ASSERT_THAT( + getsockopt(bound.get(), SOL_SOCKET, SO_ACCEPTCONN, &opt, &opt_len), + SyscallSucceeds()); + ASSERT_EQ(opt, 1); +} + INSTANTIATE_TEST_SUITE_P( AllUnixDomainSockets, StreamUnixSocketPairTest, ::testing::ValuesIn(IncludeReversals(VecCat(