diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index 7506a91b8..e2698de2d 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -326,6 +326,7 @@ func (e *connectionedEndpoint) BidirectionalConnect(ctx context.Context, ce Conn ne.ops.InitHandler(ne, &stackHandler{}, getSendBufferLimits, getReceiveBufferLimits) ne.ops.SetSendBufferSize(defaultBufferSize, false /* notify */) ne.ops.SetReceiveBufferSize(defaultBufferSize, false /* notify */) + ne.SocketOptions().SetPassCred(e.SocketOptions().GetPassCred()) readQueue := &queue{ReaderQueue: ce.WaiterQueue(), WriterQueue: ne.Queue, limit: defaultBufferSize} readQueue.InitRefs() diff --git a/test/syscalls/linux/socket_unix_cmsg.cc b/test/syscalls/linux/socket_unix_cmsg.cc index 6191b1448..acda2e7ab 100644 --- a/test/syscalls/linux/socket_unix_cmsg.cc +++ b/test/syscalls/linux/socket_unix_cmsg.cc @@ -1423,6 +1423,36 @@ TEST_P(UnixSocketPairCmsgTest, FDPassAfterSoPassCredWithoutCredSpace) { EXPECT_EQ(cmsg->cmsg_type, SCM_CREDENTIALS); } +TEST_P(UnixSocketPairCmsgTest, InheritPasscred) { + // Create an abstract server, but set SO_PASSCRED on it + struct sockaddr_un bind_addr = + ASSERT_NO_ERRNO_AND_VALUE(UniqueUnixAddr(true, AF_UNIX)); + auto bound = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, 0)); + SetSoPassCred(bound.get()); + ASSERT_THAT(bind(bound.get(), AsSockAddr(&bind_addr), sizeof(bind_addr)), + SyscallSucceeds()); + ASSERT_THAT(listen(bound.get(), + /* backlog = */ 5), // NOLINT(bugprone-argument-comment) + SyscallSucceeds()); + + // Create a connected socket pair using the server + auto connected = ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_UNIX, SOCK_STREAM, 0)); + ASSERT_THAT( + connect(connected.get(), AsSockAddr(&bind_addr), sizeof(bind_addr)), + SyscallSucceeds()); + auto accepted = + ASSERT_NO_ERRNO_AND_VALUE(Accept4(bound.get(), nullptr, nullptr, 0)); + ASSERT_THAT(close(bound.release()), SyscallSucceeds()); + + // The accepted socket should have SO_PASSCRED set + int opt; + socklen_t optLen = sizeof(opt); + EXPECT_THAT( + getsockopt(accepted.get(), SOL_SOCKET, SO_PASSCRED, &opt, &optLen), + SyscallSucceeds()); + EXPECT_TRUE(opt); +} + // This test will validate that MSG_CTRUNC as an input flag to recvmsg will // not appear as an output flag on the control message when truncation doesn't // happen.