summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/socket')
-rw-r--r--pkg/sentry/socket/epsocket/epsocket.go20
-rw-r--r--pkg/sentry/socket/epsocket/provider.go35
-rw-r--r--pkg/sentry/socket/epsocket/stack.go5
-rw-r--r--pkg/sentry/socket/hostinet/stack.go5
-rw-r--r--pkg/sentry/socket/rpcinet/stack.go5
-rw-r--r--pkg/sentry/socket/unix/unix.go10
6 files changed, 64 insertions, 16 deletions
diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go
index 9d1bcfd41..69eff7373 100644
--- a/pkg/sentry/socket/epsocket/epsocket.go
+++ b/pkg/sentry/socket/epsocket/epsocket.go
@@ -867,6 +867,18 @@ func getSockOptTCP(t *kernel.Task, ep commonEndpoint, name, outLen int) (interfa
return int32(v), nil
+ case linux.TCP_MAXSEG:
+ if outLen < sizeOfInt32 {
+ return nil, syserr.ErrInvalidArgument
+ }
+
+ var v tcpip.MaxSegOption
+ if err := ep.GetSockOpt(&v); err != nil {
+ return nil, syserr.TranslateNetstackError(err)
+ }
+
+ return int32(v), nil
+
case linux.TCP_KEEPIDLE:
if outLen < sizeOfInt32 {
return nil, syserr.ErrInvalidArgument
@@ -1219,6 +1231,14 @@ func setSockOptTCP(t *kernel.Task, ep commonEndpoint, name int, optVal []byte) *
v := usermem.ByteOrder.Uint32(optVal)
return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.QuickAckOption(v)))
+ case linux.TCP_MAXSEG:
+ if len(optVal) < sizeOfInt32 {
+ return syserr.ErrInvalidArgument
+ }
+
+ v := usermem.ByteOrder.Uint32(optVal)
+ return syserr.TranslateNetstackError(ep.SetSockOpt(tcpip.MaxSegOption(v)))
+
case linux.TCP_KEEPIDLE:
if len(optVal) < sizeOfInt32 {
return syserr.ErrInvalidArgument
diff --git a/pkg/sentry/socket/epsocket/provider.go b/pkg/sentry/socket/epsocket/provider.go
index 6d2b5d038..421f93dc4 100644
--- a/pkg/sentry/socket/epsocket/provider.go
+++ b/pkg/sentry/socket/epsocket/provider.go
@@ -40,42 +40,49 @@ type provider struct {
}
// getTransportProtocol figures out transport protocol. Currently only TCP,
-// UDP, and ICMP are supported.
-func getTransportProtocol(ctx context.Context, stype linux.SockType, protocol int) (tcpip.TransportProtocolNumber, *syserr.Error) {
+// UDP, and ICMP are supported. The bool return value is true when this socket
+// is associated with a transport protocol. This is only false for SOCK_RAW,
+// IPPROTO_IP sockets.
+func getTransportProtocol(ctx context.Context, stype linux.SockType, protocol int) (tcpip.TransportProtocolNumber, bool, *syserr.Error) {
switch stype {
case linux.SOCK_STREAM:
if protocol != 0 && protocol != syscall.IPPROTO_TCP {
- return 0, syserr.ErrInvalidArgument
+ return 0, true, syserr.ErrInvalidArgument
}
- return tcp.ProtocolNumber, nil
+ return tcp.ProtocolNumber, true, nil
case linux.SOCK_DGRAM:
switch protocol {
case 0, syscall.IPPROTO_UDP:
- return udp.ProtocolNumber, nil
+ return udp.ProtocolNumber, true, nil
case syscall.IPPROTO_ICMP:
- return header.ICMPv4ProtocolNumber, nil
+ return header.ICMPv4ProtocolNumber, true, nil
case syscall.IPPROTO_ICMPV6:
- return header.ICMPv6ProtocolNumber, nil
+ return header.ICMPv6ProtocolNumber, true, nil
}
case linux.SOCK_RAW:
// Raw sockets require CAP_NET_RAW.
creds := auth.CredentialsFromContext(ctx)
if !creds.HasCapability(linux.CAP_NET_RAW) {
- return 0, syserr.ErrPermissionDenied
+ return 0, true, syserr.ErrPermissionDenied
}
switch protocol {
case syscall.IPPROTO_ICMP:
- return header.ICMPv4ProtocolNumber, nil
+ return header.ICMPv4ProtocolNumber, true, nil
case syscall.IPPROTO_UDP:
- return header.UDPProtocolNumber, nil
+ return header.UDPProtocolNumber, true, nil
case syscall.IPPROTO_TCP:
- return header.TCPProtocolNumber, nil
+ return header.TCPProtocolNumber, true, nil
+ // IPPROTO_RAW signifies that the raw socket isn't assigned to
+ // a transport protocol. Users will be able to write packets'
+ // IP headers and won't receive anything.
+ case syscall.IPPROTO_RAW:
+ return tcpip.TransportProtocolNumber(0), false, nil
}
}
- return 0, syserr.ErrProtocolNotSupported
+ return 0, true, syserr.ErrProtocolNotSupported
}
// Socket creates a new socket object for the AF_INET or AF_INET6 family.
@@ -93,7 +100,7 @@ func (p *provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*
}
// Figure out the transport protocol.
- transProto, err := getTransportProtocol(t, stype, protocol)
+ transProto, associated, err := getTransportProtocol(t, stype, protocol)
if err != nil {
return nil, err
}
@@ -103,7 +110,7 @@ func (p *provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*
var e *tcpip.Error
wq := &waiter.Queue{}
if stype == linux.SOCK_RAW {
- ep, e = eps.Stack.NewRawEndpoint(transProto, p.netProto, wq)
+ ep, e = eps.Stack.NewRawEndpoint(transProto, p.netProto, wq, associated)
} else {
ep, e = eps.Stack.NewEndpoint(transProto, p.netProto, wq)
}
diff --git a/pkg/sentry/socket/epsocket/stack.go b/pkg/sentry/socket/epsocket/stack.go
index 1627a4f68..7eef19f74 100644
--- a/pkg/sentry/socket/epsocket/stack.go
+++ b/pkg/sentry/socket/epsocket/stack.go
@@ -138,3 +138,8 @@ func (s *Stack) TCPSACKEnabled() (bool, error) {
func (s *Stack) SetTCPSACKEnabled(enabled bool) error {
return syserr.TranslateNetstackError(s.Stack.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.SACKEnabled(enabled))).ToError()
}
+
+// Statistics implements inet.Stack.Statistics.
+func (s *Stack) Statistics(stat interface{}, arg string) error {
+ return syserr.ErrEndpointOperation.ToError()
+}
diff --git a/pkg/sentry/socket/hostinet/stack.go b/pkg/sentry/socket/hostinet/stack.go
index 11f94281c..cc1f66fa1 100644
--- a/pkg/sentry/socket/hostinet/stack.go
+++ b/pkg/sentry/socket/hostinet/stack.go
@@ -244,3 +244,8 @@ func (s *Stack) TCPSACKEnabled() (bool, error) {
func (s *Stack) SetTCPSACKEnabled(enabled bool) error {
return syserror.EACCES
}
+
+// Statistics implements inet.Stack.Statistics.
+func (s *Stack) Statistics(stat interface{}, arg string) error {
+ return syserror.EOPNOTSUPP
+}
diff --git a/pkg/sentry/socket/rpcinet/stack.go b/pkg/sentry/socket/rpcinet/stack.go
index 3038f25a7..49bd3a220 100644
--- a/pkg/sentry/socket/rpcinet/stack.go
+++ b/pkg/sentry/socket/rpcinet/stack.go
@@ -133,3 +133,8 @@ func (s *Stack) TCPSACKEnabled() (bool, error) {
func (s *Stack) SetTCPSACKEnabled(enabled bool) error {
panic("rpcinet handles procfs directly this method should not be called")
}
+
+// Statistics implements inet.Stack.Statistics.
+func (s *Stack) Statistics(stat interface{}, arg string) error {
+ return syserr.ErrEndpointOperation.ToError()
+}
diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go
index 637168714..eb262ecaf 100644
--- a/pkg/sentry/socket/unix/unix.go
+++ b/pkg/sentry/socket/unix/unix.go
@@ -68,6 +68,12 @@ func New(ctx context.Context, endpoint transport.Endpoint, stype linux.SockType)
// NewWithDirent creates a new unix socket using an existing dirent.
func NewWithDirent(ctx context.Context, d *fs.Dirent, ep transport.Endpoint, stype linux.SockType, flags fs.FileFlags) *fs.File {
+ // You can create AF_UNIX, SOCK_RAW sockets. They're the same as
+ // SOCK_DGRAM and don't require CAP_NET_RAW.
+ if stype == linux.SOCK_RAW {
+ stype = linux.SOCK_DGRAM
+ }
+
s := SocketOperations{
ep: ep,
stype: stype,
@@ -639,7 +645,7 @@ func (*provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*fs
// Create the endpoint and socket.
var ep transport.Endpoint
switch stype {
- case linux.SOCK_DGRAM:
+ case linux.SOCK_DGRAM, linux.SOCK_RAW:
ep = transport.NewConnectionless(t)
case linux.SOCK_SEQPACKET, linux.SOCK_STREAM:
ep = transport.NewConnectioned(t, stype, t.Kernel())
@@ -658,7 +664,7 @@ func (*provider) Pair(t *kernel.Task, stype linux.SockType, protocol int) (*fs.F
}
switch stype {
- case linux.SOCK_STREAM, linux.SOCK_DGRAM, linux.SOCK_SEQPACKET:
+ case linux.SOCK_STREAM, linux.SOCK_DGRAM, linux.SOCK_SEQPACKET, linux.SOCK_RAW:
// Ok
default:
return nil, nil, syserr.ErrInvalidArgument