Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions pkg/sentry/socket/unix/unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ type Socket struct {

var _ = socket.Socket(&Socket{})

func isAbstract(path string) bool {
return len(path) == 0 || path[0] == 0
}

// NewSockfsFile creates a new socket file in the global sockfs mount and
// returns a corresponding file description.
func NewSockfsFile(t *kernel.Task, ep transport.Endpoint, stype linux.SockType) (*vfs.FileDescription, *syserr.Error) {
Expand Down Expand Up @@ -224,7 +228,7 @@ func (s *Socket) Bind(t *kernel.Task, sockaddr []byte) *syserr.Error {
}

// If path is empty, the socket is autobound to an abstract address.
if len(p) == 0 || p[0] == 0 {
if isAbstract(p) {
// Abstract socket. See net/unix/af_unix.c:unix_bind_abstract().
asn := s.namespace.AbstractSockets()
p, err := asn.Bind(t, p, bep, s)
Expand Down Expand Up @@ -469,8 +473,8 @@ func extractPath(sockaddr []byte) (string, *syserr.Error) {

// The address is trimmed by GetAddress.
p := addr.Addr
if len(p) > 0 && p[len(p)-1] == '/' {
// Weird, they tried to bind '/a/b/c/'?
if !isAbstract(p) && p[len(p)-1] == '/' {
// Weird, they tried to bind '/a/b/c/' on a filesystem socket?
return "", syserr.ErrIsDir
}

Expand Down Expand Up @@ -578,7 +582,7 @@ func (s *Socket) extractEndpoint(t *kernel.Task, sockaddr []byte) (transport.Bou
}

// Is it abstract?
if path[0] == 0 {
if isAbstract(path) {
ep := s.namespace.AbstractSockets().BoundEndpoint(path[1:])
if ep == nil {
// No socket found.
Expand Down Expand Up @@ -630,7 +634,7 @@ func (s *Socket) Connect(t *kernel.Task, sockaddr []byte, blocking bool) *syserr
// Linux for abstract sockets returns ErrConnectionRefused
// instead of ErrWrongProtocolForSocket.
path, _ := extractPath(sockaddr)
if len(path) > 0 && path[0] == 0 {
if isAbstract(path) {
err = syserr.ErrConnectionRefused
}
}
Expand Down
20 changes: 20 additions & 0 deletions test/syscalls/linux/socket_unix_unbound_abstract.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@ TEST_P(UnboundAbstractUnixSocketPairTest, AddressAfterNull) {
SyscallSucceeds());
}

TEST_P(UnboundAbstractUnixSocketPairTest, TrailingSlash) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

struct sockaddr_un addr =
*reinterpret_cast<const struct sockaddr_un*>(sockets->first_addr());
ASSERT_EQ(addr.sun_path[0], 0);

// Safe because sun_path for abstract sockets is not null terminated.
// See unix(7).
addr.sun_path[sizeof(addr.sun_path) - 1] = '/';

ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
sockets->first_addr_size()),
SyscallSucceeds());

ASSERT_THAT(bind(sockets->second_fd(),
reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)),
SyscallSucceeds());
}

TEST_P(UnboundAbstractUnixSocketPairTest, ShortAddressNotExtended) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

Expand Down
Loading