From 8478fe0a277fd2581f8df5560a310daa7277ed15 Mon Sep 17 00:00:00 2001 From: Kevin Krakauer Date: Fri, 21 Apr 2023 16:46:19 -0700 Subject: [PATCH] stop using tcpip.FullAddress with unix sockets It's unnecessarily overloading the type, which makes it hard to change the type in netstack. PiperOrigin-RevId: 526168235 --- pkg/sentry/socket/netlink/BUILD | 1 - pkg/sentry/socket/netlink/socket.go | 7 ++- pkg/sentry/socket/netstack/netstack.go | 8 --- pkg/sentry/socket/socket.go | 18 ------- pkg/sentry/socket/unix/io.go | 3 +- .../socket/unix/transport/connectioned.go | 8 +-- .../socket/unix/transport/connectionless.go | 9 ++-- pkg/sentry/socket/unix/transport/host.go | 18 +++---- pkg/sentry/socket/unix/transport/queue.go | 3 +- pkg/sentry/socket/unix/transport/unix.go | 53 +++++++++++-------- pkg/sentry/socket/unix/unix.go | 43 ++++++++++----- 11 files changed, 83 insertions(+), 88 deletions(-) diff --git a/pkg/sentry/socket/netlink/BUILD b/pkg/sentry/socket/netlink/BUILD index 09d0328e8..0f81b5a31 100644 --- a/pkg/sentry/socket/netlink/BUILD +++ b/pkg/sentry/socket/netlink/BUILD @@ -35,7 +35,6 @@ go_library( "//pkg/sentry/vfs", "//pkg/sync", "//pkg/syserr", - "//pkg/tcpip", "//pkg/usermem", "//pkg/waiter", ], diff --git a/pkg/sentry/socket/netlink/socket.go b/pkg/sentry/socket/netlink/socket.go index ef82f7c7b..a22357d86 100644 --- a/pkg/sentry/socket/netlink/socket.go +++ b/pkg/sentry/socket/netlink/socket.go @@ -38,7 +38,6 @@ import ( "gvisor.dev/gvisor/pkg/sentry/vfs" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/syserr" - "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/usermem" "gvisor.dev/gvisor/pkg/waiter" ) @@ -124,7 +123,7 @@ func New(t *kernel.Task, skType linux.SockType, protocol Protocol) (*Socket, *sy // Bind the endpoint for good measure so we can connect to it. The // bound address will never be exposed. - if err := ep.Bind(tcpip.FullAddress{Addr: "dummy"}); err != nil { + if err := ep.Bind(transport.Address{Addr: "dummy"}); err != nil { ep.Close(t) return nil, err } @@ -629,7 +628,7 @@ func (s *Socket) sendResponse(ctx context.Context, ms *MessageSet) *syserr.Error if len(bufs) > 0 { // RecvMsg never receives the address, so we don't need to send // one. - _, notify, err := s.connection.Send(ctx, bufs, cms, tcpip.FullAddress{}) + _, notify, err := s.connection.Send(ctx, bufs, cms, transport.Address{}) // If the buffer is full, we simply drop messages, just like // Linux. if err != nil && err != syserr.ErrWouldBlock { @@ -656,7 +655,7 @@ func (s *Socket) sendResponse(ctx context.Context, ms *MessageSet) *syserr.Error // Add the dump_done_errno payload. m.Put(primitive.AllocateInt64(0)) - _, notify, err := s.connection.Send(ctx, [][]byte{m.Finalize()}, cms, tcpip.FullAddress{}) + _, notify, err := s.connection.Send(ctx, [][]byte{m.Finalize()}, cms, transport.Address{}) if err != nil && err != syserr.ErrWouldBlock { return err } diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index b0a3523b6..8a52962a0 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -301,14 +301,6 @@ var errStackType = syserr.New("expected but did not receive a netstack.Stack", e // commonEndpoint represents the intersection of a tcpip.Endpoint and a // transport.Endpoint. type commonEndpoint interface { - // GetLocalAddress implements tcpip.Endpoint.GetLocalAddress and - // transport.Endpoint.GetLocalAddress. - GetLocalAddress() (tcpip.FullAddress, tcpip.Error) - - // GetRemoteAddress implements tcpip.Endpoint.GetRemoteAddress and - // transport.Endpoint.GetRemoteAddress. - GetRemoteAddress() (tcpip.FullAddress, tcpip.Error) - // Readiness implements tcpip.Endpoint.Readiness and // transport.Endpoint.Readiness. Readiness(mask waiter.EventMask) waiter.EventMask diff --git a/pkg/sentry/socket/socket.go b/pkg/sentry/socket/socket.go index 7fdff04c6..4b930b166 100644 --- a/pkg/sentry/socket/socket.go +++ b/pkg/sentry/socket/socket.go @@ -467,24 +467,6 @@ func isLinkLocal(addr tcpip.Address) bool { // ConvertAddress converts the given address to a native format. func ConvertAddress(family int, addr tcpip.FullAddress) (linux.SockAddr, uint32) { switch family { - case linux.AF_UNIX: - var out linux.SockAddrUnix - out.Family = linux.AF_UNIX - l := len([]byte(addr.Addr)) - for i := 0; i < l; i++ { - out.Path[i] = int8(addr.Addr[i]) - } - - // Linux returns the used length of the address struct (including the - // null terminator) for filesystem paths. The Family field is 2 bytes. - // It is sometimes allowed to exclude the null terminator if the - // address length is the max. Abstract and empty paths always return - // the full exact length. - if l == 0 || out.Path[0] == 0 || l == len(out.Path) { - return &out, uint32(2 + l) - } - return &out, uint32(3 + l) - case linux.AF_INET: var out linux.SockAddrInet copy(out.Addr[:], addr.Addr) diff --git a/pkg/sentry/socket/unix/io.go b/pkg/sentry/socket/unix/io.go index 619a4c64d..9cb477de7 100644 --- a/pkg/sentry/socket/unix/io.go +++ b/pkg/sentry/socket/unix/io.go @@ -18,7 +18,6 @@ import ( "gvisor.dev/gvisor/pkg/context" "gvisor.dev/gvisor/pkg/safemem" "gvisor.dev/gvisor/pkg/sentry/socket/unix/transport" - "gvisor.dev/gvisor/pkg/tcpip" ) // EndpointWriter implements safemem.Writer that writes to a transport.Endpoint. @@ -79,7 +78,7 @@ type EndpointReader struct { MsgSize int64 // From, if not nil, will be set with the address read from. - From *tcpip.FullAddress + From *transport.Address // Control contains the received control messages. Control transport.ControlMessages diff --git a/pkg/sentry/socket/unix/transport/connectioned.go b/pkg/sentry/socket/unix/transport/connectioned.go index 87f9bb460..d5089de79 100644 --- a/pkg/sentry/socket/unix/transport/connectioned.go +++ b/pkg/sentry/socket/unix/transport/connectioned.go @@ -50,7 +50,7 @@ type ConnectingEndpoint interface { Type() linux.SockType // GetLocalAddress returns the bound path. - GetLocalAddress() (tcpip.FullAddress, tcpip.Error) + GetLocalAddress() (Address, tcpip.Error) // Locker protects the following methods. While locked, only the holder of // the lock can change the return value of the protected methods. @@ -438,7 +438,7 @@ func (e *connectionedEndpoint) Listen(ctx context.Context, backlog int) *syserr. } // Accept accepts a new connection. -func (e *connectionedEndpoint) Accept(ctx context.Context, peerAddr *tcpip.FullAddress) (Endpoint, *syserr.Error) { +func (e *connectionedEndpoint) Accept(ctx context.Context, peerAddr *Address) (Endpoint, *syserr.Error) { e.Lock() if !e.ListeningLocked() { @@ -511,7 +511,7 @@ func (e *connectionedEndpoint) getAcceptedEndpointLocked(ctx context.Context) (* // // Bind will fail only if the socket is connected, bound or the passed address // is invalid (the empty string). -func (e *connectionedEndpoint) Bind(addr tcpip.FullAddress) *syserr.Error { +func (e *connectionedEndpoint) Bind(addr Address) *syserr.Error { e.Lock() defer e.Unlock() if e.isBound() || e.ListeningLocked() { @@ -523,7 +523,7 @@ func (e *connectionedEndpoint) Bind(addr tcpip.FullAddress) *syserr.Error { } // Save the bound address. - e.path = string(addr.Addr) + e.path = addr.Addr return nil } diff --git a/pkg/sentry/socket/unix/transport/connectionless.go b/pkg/sentry/socket/unix/transport/connectionless.go index 6df52623c..b69f90901 100644 --- a/pkg/sentry/socket/unix/transport/connectionless.go +++ b/pkg/sentry/socket/unix/transport/connectionless.go @@ -18,7 +18,6 @@ import ( "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/context" "gvisor.dev/gvisor/pkg/syserr" - "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/waiter" ) @@ -115,7 +114,7 @@ func (e *connectionlessEndpoint) SendMsg(ctx context.Context, data [][]byte, c C defer connected.Release(ctx) e.Lock() - n, notify, err := connected.Send(ctx, data, c, tcpip.FullAddress{Addr: tcpip.Address(e.path)}) + n, notify, err := connected.Send(ctx, data, c, Address{Addr: e.path}) e.Unlock() var notifyFn func() @@ -154,7 +153,7 @@ func (*connectionlessEndpoint) Listen(context.Context, int) *syserr.Error { } // Accept accepts a new connection. -func (*connectionlessEndpoint) Accept(context.Context, *tcpip.FullAddress) (Endpoint, *syserr.Error) { +func (*connectionlessEndpoint) Accept(context.Context, *Address) (Endpoint, *syserr.Error) { return nil, syserr.ErrNotSupported } @@ -166,7 +165,7 @@ func (*connectionlessEndpoint) Accept(context.Context, *tcpip.FullAddress) (Endp // // Bind will fail only if the socket is connected, bound or the passed address // is invalid (the empty string). -func (e *connectionlessEndpoint) Bind(addr tcpip.FullAddress) *syserr.Error { +func (e *connectionlessEndpoint) Bind(addr Address) *syserr.Error { e.Lock() defer e.Unlock() if e.isBound() { @@ -178,7 +177,7 @@ func (e *connectionlessEndpoint) Bind(addr tcpip.FullAddress) *syserr.Error { } // Save the bound address. - e.path = string(addr.Addr) + e.path = addr.Addr return nil } diff --git a/pkg/sentry/socket/unix/transport/host.go b/pkg/sentry/socket/unix/transport/host.go index 9ed26e604..06a298fac 100644 --- a/pkg/sentry/socket/unix/transport/host.go +++ b/pkg/sentry/socket/unix/transport/host.go @@ -149,7 +149,7 @@ func (c *HostConnectedEndpoint) SockType() linux.SockType { } // Send implements ConnectedEndpoint.Send. -func (c *HostConnectedEndpoint) Send(ctx context.Context, data [][]byte, controlMessages ControlMessages, from tcpip.FullAddress) (int64, bool, *syserr.Error) { +func (c *HostConnectedEndpoint) Send(ctx context.Context, data [][]byte, controlMessages ControlMessages, from Address) (int64, bool, *syserr.Error) { c.mu.RLock() defer c.mu.RUnlock() @@ -212,8 +212,8 @@ func (c *HostConnectedEndpoint) Passcred() bool { } // GetLocalAddress implements ConnectedEndpoint.GetLocalAddress. -func (c *HostConnectedEndpoint) GetLocalAddress() (tcpip.FullAddress, tcpip.Error) { - return tcpip.FullAddress{Addr: tcpip.Address(c.addr)}, nil +func (c *HostConnectedEndpoint) GetLocalAddress() (Address, tcpip.Error) { + return Address{Addr: c.addr}, nil } // EventUpdate implements ConnectedEndpoint.EventUpdate. @@ -229,7 +229,7 @@ func (c *HostConnectedEndpoint) EventUpdate() error { } // Recv implements Receiver.Recv. -func (c *HostConnectedEndpoint) Recv(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool) (int64, int64, ControlMessages, bool, tcpip.FullAddress, bool, *syserr.Error) { +func (c *HostConnectedEndpoint) Recv(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool) (int64, int64, ControlMessages, bool, Address, bool, *syserr.Error) { c.mu.RLock() defer c.mu.RUnlock() @@ -248,7 +248,7 @@ func (c *HostConnectedEndpoint) Recv(ctx context.Context, data [][]byte, creds b err = nil } if err != nil { - return 0, 0, ControlMessages{}, false, tcpip.FullAddress{}, false, syserr.FromError(err) + return 0, 0, ControlMessages{}, false, Address{}, false, syserr.FromError(err) } // There is no need for the callee to call RecvNotify because fdReadVec uses @@ -261,18 +261,18 @@ func (c *HostConnectedEndpoint) Recv(ctx context.Context, data [][]byte, creds b // Avoid extra allocations in the case where there isn't any control data. if len(cm) == 0 { - return rl, ml, ControlMessages{}, cTrunc, tcpip.FullAddress{Addr: tcpip.Address(c.addr)}, false, nil + return rl, ml, ControlMessages{}, cTrunc, Address{Addr: c.addr}, false, nil } fds, err := cm.ExtractFDs() if err != nil { - return 0, 0, ControlMessages{}, false, tcpip.FullAddress{}, false, syserr.FromError(err) + return 0, 0, ControlMessages{}, false, Address{}, false, syserr.FromError(err) } if len(fds) == 0 { - return rl, ml, ControlMessages{}, cTrunc, tcpip.FullAddress{Addr: tcpip.Address(c.addr)}, false, nil + return rl, ml, ControlMessages{}, cTrunc, Address{Addr: c.addr}, false, nil } - return rl, ml, ControlMessages{Rights: &SCMRights{fds}}, cTrunc, tcpip.FullAddress{Addr: tcpip.Address(c.addr)}, false, nil + return rl, ml, ControlMessages{Rights: &SCMRights{fds}}, cTrunc, Address{Addr: c.addr}, false, nil } // RecvNotify implements Receiver.RecvNotify. diff --git a/pkg/sentry/socket/unix/transport/queue.go b/pkg/sentry/socket/unix/transport/queue.go index 5d811a9d1..81beb7362 100644 --- a/pkg/sentry/socket/unix/transport/queue.go +++ b/pkg/sentry/socket/unix/transport/queue.go @@ -17,7 +17,6 @@ package transport import ( "gvisor.dev/gvisor/pkg/context" "gvisor.dev/gvisor/pkg/syserr" - "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/waiter" ) @@ -113,7 +112,7 @@ func (q *queue) IsWritable() bool { // // If notify is true, ReaderQueue.Notify must be called: // q.ReaderQueue.Notify(waiter.ReadableEvents) -func (q *queue) Enqueue(ctx context.Context, data [][]byte, c ControlMessages, from tcpip.FullAddress, discardEmpty bool, truncate bool) (l int64, notify bool, err *syserr.Error) { +func (q *queue) Enqueue(ctx context.Context, data [][]byte, c ControlMessages, from Address, discardEmpty bool, truncate bool) (l int64, notify bool, err *syserr.Error) { q.mu.Lock() if q.closed { diff --git a/pkg/sentry/socket/unix/transport/unix.go b/pkg/sentry/socket/unix/transport/unix.go index ce1e96616..58d2c6409 100644 --- a/pkg/sentry/socket/unix/transport/unix.go +++ b/pkg/sentry/socket/unix/transport/unix.go @@ -131,7 +131,7 @@ type Endpoint interface { // // If set, notify is a callback that should be called after RecvMesg // completes without mm.activeMu held. - RecvMsg(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool, addr *tcpip.FullAddress) (recvLen, msgLen int64, cm ControlMessages, CMTruncated bool, notify func(), err *syserr.Error) + RecvMsg(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool, addr *Address) (recvLen, msgLen int64, cm ControlMessages, CMTruncated bool, notify func(), err *syserr.Error) // SendMsg writes data and a control message to the endpoint's peer. // This method does not block if the data cannot be written. @@ -166,22 +166,22 @@ type Endpoint interface { // // peerAddr if not nil will be populated with the address of the connected // peer on a successful accept. - Accept(ctx context.Context, peerAddr *tcpip.FullAddress) (Endpoint, *syserr.Error) + Accept(ctx context.Context, peerAddr *Address) (Endpoint, *syserr.Error) // Bind binds the endpoint to a specific local address and port. // Specifying a NIC is optional. - Bind(address tcpip.FullAddress) *syserr.Error + Bind(address Address) *syserr.Error // Type return the socket type, typically either SockStream, SockDgram // or SockSeqpacket. Type() linux.SockType // GetLocalAddress returns the address to which the endpoint is bound. - GetLocalAddress() (tcpip.FullAddress, tcpip.Error) + GetLocalAddress() (Address, tcpip.Error) // GetRemoteAddress returns the address to which the endpoint is // connected. - GetRemoteAddress() (tcpip.FullAddress, tcpip.Error) + GetRemoteAddress() (Address, tcpip.Error) // SetSockOpt sets a socket option. SetSockOpt(opt tcpip.SettableSocketOption) tcpip.Error @@ -312,7 +312,7 @@ type message struct { // // If the endpoint that sent the message is not bound, the Address is // the empty string. - Address tcpip.FullAddress + Address Address } // Length returns number of bytes stored in the message. @@ -344,7 +344,7 @@ type Receiver interface { // See Endpoint.RecvMsg for documentation on shared arguments. // // notify indicates if RecvNotify should be called. - Recv(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool) (recvLen, msgLen int64, cm ControlMessages, CMTruncated bool, source tcpip.FullAddress, notify bool, err *syserr.Error) + Recv(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool) (recvLen, msgLen int64, cm ControlMessages, CMTruncated bool, source Address, notify bool, err *syserr.Error) // RecvNotify notifies the Receiver of a successful Recv. This must not be // called while holding any endpoint locks. @@ -376,6 +376,13 @@ type Receiver interface { Release(ctx context.Context) } +// Address is a unix socket address. +// +// +stateify savable +type Address struct { + Addr string +} + // queueReceiver implements Receiver for datagram sockets. // // +stateify savable @@ -384,7 +391,7 @@ type queueReceiver struct { } // Recv implements Receiver.Recv. -func (q *queueReceiver) Recv(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool) (int64, int64, ControlMessages, bool, tcpip.FullAddress, bool, *syserr.Error) { +func (q *queueReceiver) Recv(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool) (int64, int64, ControlMessages, bool, Address, bool, *syserr.Error) { var m *message var notify bool var err *syserr.Error @@ -394,7 +401,7 @@ func (q *queueReceiver) Recv(ctx context.Context, data [][]byte, creds bool, num m, notify, err = q.readQueue.Dequeue() } if err != nil { - return 0, 0, ControlMessages{}, false, tcpip.FullAddress{}, false, err + return 0, 0, ControlMessages{}, false, Address{}, false, err } src := []byte(m.Data) var copied int64 @@ -451,7 +458,7 @@ type streamQueueReceiver struct { mu streamQueueReceiverMutex `state:"nosave"` buffer []byte control ControlMessages - addr tcpip.FullAddress + addr Address } func vecCopy(data [][]byte, buf []byte) (int64, [][]byte, []byte) { @@ -496,7 +503,7 @@ func (q *streamQueueReceiver) RecvMaxQueueSize() int64 { } // Recv implements Receiver.Recv. -func (q *streamQueueReceiver) Recv(ctx context.Context, data [][]byte, wantCreds bool, numRights int, peek bool) (int64, int64, ControlMessages, bool, tcpip.FullAddress, bool, *syserr.Error) { +func (q *streamQueueReceiver) Recv(ctx context.Context, data [][]byte, wantCreds bool, numRights int, peek bool) (int64, int64, ControlMessages, bool, Address, bool, *syserr.Error) { q.mu.Lock() defer q.mu.Unlock() @@ -509,7 +516,7 @@ func (q *streamQueueReceiver) Recv(ctx context.Context, data [][]byte, wantCreds // the next time Recv() is called. m, n, err := q.readQueue.Dequeue() if err != nil { - return 0, 0, ControlMessages{}, false, tcpip.FullAddress{}, false, err + return 0, 0, ControlMessages{}, false, Address{}, false, err } notify = n q.buffer = []byte(m.Data) @@ -620,7 +627,7 @@ type ConnectedEndpoint interface { Passcred() bool // GetLocalAddress implements Endpoint.GetLocalAddress. - GetLocalAddress() (tcpip.FullAddress, tcpip.Error) + GetLocalAddress() (Address, tcpip.Error) // Send sends a single message. This method does not block. // @@ -628,7 +635,7 @@ type ConnectedEndpoint interface { // // syserr.ErrWouldBlock can be returned along with a partial write if // the caller should block to send the rest of the data. - Send(ctx context.Context, data [][]byte, c ControlMessages, from tcpip.FullAddress) (n int64, notify bool, err *syserr.Error) + Send(ctx context.Context, data [][]byte, c ControlMessages, from Address) (n int64, notify bool, err *syserr.Error) // SendNotify notifies the ConnectedEndpoint of a successful Send. This // must not be called while holding any endpoint locks. @@ -684,7 +691,7 @@ type connectedEndpoint struct { Passcred() bool // GetLocalAddress implements Endpoint.GetLocalAddress. - GetLocalAddress() (tcpip.FullAddress, tcpip.Error) + GetLocalAddress() (Address, tcpip.Error) // Type implements Endpoint.Type. Type() linux.SockType @@ -699,12 +706,12 @@ func (e *connectedEndpoint) Passcred() bool { } // GetLocalAddress implements ConnectedEndpoint.GetLocalAddress. -func (e *connectedEndpoint) GetLocalAddress() (tcpip.FullAddress, tcpip.Error) { +func (e *connectedEndpoint) GetLocalAddress() (Address, tcpip.Error) { return e.endpoint.GetLocalAddress() } // Send implements ConnectedEndpoint.Send. -func (e *connectedEndpoint) Send(ctx context.Context, data [][]byte, c ControlMessages, from tcpip.FullAddress) (int64, bool, *syserr.Error) { +func (e *connectedEndpoint) Send(ctx context.Context, data [][]byte, c ControlMessages, from Address) (int64, bool, *syserr.Error) { discardEmpty := false truncate := false if e.endpoint.Type() == linux.SOCK_STREAM { @@ -852,7 +859,7 @@ func (e *baseEndpoint) Connected() bool { } // RecvMsg reads data and a control message from the endpoint. -func (e *baseEndpoint) RecvMsg(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool, addr *tcpip.FullAddress) (int64, int64, ControlMessages, bool, func(), *syserr.Error) { +func (e *baseEndpoint) RecvMsg(ctx context.Context, data [][]byte, creds bool, numRights int, peek bool, addr *Address) (int64, int64, ControlMessages, bool, func(), *syserr.Error) { e.Lock() receiver := e.receiver @@ -892,7 +899,7 @@ func (e *baseEndpoint) SendMsg(ctx context.Context, data [][]byte, c ControlMess } connected := e.connected - n, notify, err := connected.Send(ctx, data, c, tcpip.FullAddress{Addr: tcpip.Address(e.path)}) + n, notify, err := connected.Send(ctx, data, c, Address{Addr: e.path}) e.Unlock() var notifyFn func() @@ -999,22 +1006,22 @@ func (e *baseEndpoint) Shutdown(flags tcpip.ShutdownFlags) *syserr.Error { } // GetLocalAddress returns the bound path. -func (e *baseEndpoint) GetLocalAddress() (tcpip.FullAddress, tcpip.Error) { +func (e *baseEndpoint) GetLocalAddress() (Address, tcpip.Error) { e.Lock() defer e.Unlock() - return tcpip.FullAddress{Addr: tcpip.Address(e.path)}, nil + return Address{Addr: e.path}, nil } // GetRemoteAddress returns the local address of the connected endpoint (if // available). -func (e *baseEndpoint) GetRemoteAddress() (tcpip.FullAddress, tcpip.Error) { +func (e *baseEndpoint) GetRemoteAddress() (Address, tcpip.Error) { e.Lock() c := e.connected e.Unlock() if c != nil { return c.GetLocalAddress() } - return tcpip.FullAddress{}, &tcpip.ErrNotConnected{} + return Address{}, &tcpip.ErrNotConnected{} } // Release implements BoundEndpoint.Release. diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go index 820bef6d5..e6fba71d1 100644 --- a/pkg/sentry/socket/unix/unix.go +++ b/pkg/sentry/socket/unix/unix.go @@ -37,7 +37,6 @@ import ( "gvisor.dev/gvisor/pkg/sentry/socket/unix/transport" "gvisor.dev/gvisor/pkg/sentry/vfs" "gvisor.dev/gvisor/pkg/syserr" - "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/usermem" "gvisor.dev/gvisor/pkg/waiter" ) @@ -132,7 +131,7 @@ func (s *Socket) GetSockOpt(t *kernel.Task, level, name int, outPtr hostarch.Add // blockingAccept implements a blocking version of accept(2), that is, if no // connections are ready to be accept, it will block until one becomes ready. -func (s *Socket) blockingAccept(t *kernel.Task, peerAddr *tcpip.FullAddress) (transport.Endpoint, *syserr.Error) { +func (s *Socket) blockingAccept(t *kernel.Task, peerAddr *transport.Address) (transport.Endpoint, *syserr.Error) { // Register for notifications. e, ch := waiter.NewChannelEntry(waiter.ReadableEvents) s.EventRegister(&e) @@ -154,9 +153,9 @@ func (s *Socket) blockingAccept(t *kernel.Task, peerAddr *tcpip.FullAddress) (tr // Accept implements the linux syscall accept(2) for sockets backed by // a transport.Endpoint. func (s *Socket) Accept(t *kernel.Task, peerRequested bool, flags int, blocking bool) (int32, linux.SockAddr, uint32, *syserr.Error) { - var peerAddr *tcpip.FullAddress + var peerAddr *transport.Address if peerRequested { - peerAddr = &tcpip.FullAddress{} + peerAddr = &transport.Address{} } ep, err := s.ep.Accept(t, peerAddr) if err != nil { @@ -184,7 +183,7 @@ func (s *Socket) Accept(t *kernel.Task, peerRequested bool, flags int, blocking var addr linux.SockAddr var addrLen uint32 if peerAddr != nil { - addr, addrLen = socket.ConvertAddress(linux.AF_UNIX, *peerAddr) + addr, addrLen = convertAddress(*peerAddr) } fd, e := t.NewFDFrom(0, ns, kernel.FDFlags{ @@ -222,7 +221,7 @@ func (s *Socket) Bind(t *kernel.Task, sockaddr []byte) *syserr.Error { // syserr.ErrPortInUse corresponds to EADDRINUSE. return syserr.ErrPortInUse } - if err := s.ep.Bind(tcpip.FullAddress{Addr: tcpip.Address(p)}); err != nil { + if err := s.ep.Bind(transport.Address{Addr: p}); err != nil { asn.Remove(name, s) return err } @@ -261,7 +260,7 @@ func (s *Socket) Bind(t *kernel.Task, sockaddr []byte) *syserr.Error { if err != nil { return syserr.FromError(err) } - if err := s.ep.Bind(tcpip.FullAddress{Addr: tcpip.Address(p)}); err != nil { + if err := s.ep.Bind(transport.Address{Addr: p}); err != nil { if unlinkErr := t.Kernel().VFS().UnlinkAt(t, t.Credentials(), &pop); unlinkErr != nil { log.Warningf("failed to unlink socket file created for bind(%q): %v", p, unlinkErr) } @@ -469,7 +468,7 @@ func (s *Socket) GetPeerName(t *kernel.Task) (linux.SockAddr, uint32, *syserr.Er return nil, 0, syserr.TranslateNetstackError(err) } - a, l := socket.ConvertAddress(linux.AF_UNIX, addr) + a, l := convertAddress(addr) return a, l, nil } @@ -481,7 +480,7 @@ func (s *Socket) GetSockName(t *kernel.Task) (linux.SockAddr, uint32, *syserr.Er return nil, 0, syserr.TranslateNetstackError(err) } - a, l := socket.ConvertAddress(linux.AF_UNIX, addr) + a, l := convertAddress(addr) return a, l, nil } @@ -709,7 +708,7 @@ func (s *Socket) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, have Peek: peek, } if senderRequested { - r.From = &tcpip.FullAddress{} + r.From = &transport.Address{} } doRead := func() (int64, error) { @@ -739,7 +738,7 @@ func (s *Socket) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, have var from linux.SockAddr var fromLen uint32 if r.From != nil && len([]byte(r.From.Addr)) != 0 { - from, fromLen = socket.ConvertAddress(linux.AF_UNIX, *r.From) + from, fromLen = convertAddress(*r.From) } if r.ControlTrunc { @@ -774,7 +773,7 @@ func (s *Socket) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, have var from linux.SockAddr var fromLen uint32 if r.From != nil { - from, fromLen = socket.ConvertAddress(linux.AF_UNIX, *r.From) + from, fromLen = convertAddress(*r.From) } if r.ControlTrunc { @@ -826,6 +825,26 @@ func (s *Socket) Type() (family int, skType linux.SockType, protocol int) { return linux.AF_UNIX, s.stype, 0 } +func convertAddress(addr transport.Address) (linux.SockAddr, uint32) { + var out linux.SockAddrUnix + out.Family = linux.AF_UNIX + l := len([]byte(addr.Addr)) + for i := 0; i < l; i++ { + out.Path[i] = int8(addr.Addr[i]) + } + + // Linux returns the used length of the address struct (including the + // null terminator) for filesystem paths. The Family field is 2 bytes. + // It is sometimes allowed to exclude the null terminator if the + // address length is the max. Abstract and empty paths always return + // the full exact length. + if l == 0 || out.Path[0] == 0 || l == len(out.Path) { + return &out, uint32(2 + l) + } + return &out, uint32(3 + l) + +} + func init() { socket.RegisterProvider(linux.AF_UNIX, &provider{}) }