summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket/netstack
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/socket/netstack')
-rw-r--r--pkg/sentry/socket/netstack/netstack.go47
-rw-r--r--pkg/sentry/socket/netstack/netstack_vfs2.go5
-rw-r--r--pkg/sentry/socket/netstack/stack.go12
-rw-r--r--pkg/sentry/socket/netstack/tun.go4
4 files changed, 55 insertions, 13 deletions
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go
index 11f75628c..9b844b0c0 100644
--- a/pkg/sentry/socket/netstack/netstack.go
+++ b/pkg/sentry/socket/netstack/netstack.go
@@ -49,6 +49,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel"
+ "gvisor.dev/gvisor/pkg/sentry/kernel/auth"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sentry/socket"
"gvisor.dev/gvisor/pkg/sentry/socket/netfilter"
@@ -273,6 +274,7 @@ var Metrics = tcpip.Stats{
Timeouts: mustCreateMetric("/netstack/tcp/timeouts", "Number of times RTO expired."),
ChecksumErrors: mustCreateMetric("/netstack/tcp/checksum_errors", "Number of segments dropped due to bad checksums."),
FailedPortReservations: mustCreateMetric("/netstack/tcp/failed_port_reservations", "Number of time TCP failed to reserve a port."),
+ SegmentsAckedWithDSACK: mustCreateMetric("/netstack/tcp/segments_acked_with_dsack", "Number of segments for which DSACK was received."),
},
UDP: tcpip.UDPStats{
PacketsReceived: mustCreateMetric("/netstack/udp/packets_received", "Number of UDP datagrams received via HandlePacket."),
@@ -1682,6 +1684,26 @@ func SetSockOpt(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, level int
return nil
}
+func clampBufSize(newSz, min, max int64, ignoreMax bool) int64 {
+ // packetOverheadFactor is used to multiply the value provided by the user on
+ // a setsockopt(2) for setting the send/receive buffer sizes sockets.
+ const packetOverheadFactor = 2
+
+ if !ignoreMax && newSz > max {
+ newSz = max
+ }
+
+ if newSz < math.MaxInt32/packetOverheadFactor {
+ newSz *= packetOverheadFactor
+ if newSz < min {
+ newSz = min
+ }
+ } else {
+ newSz = math.MaxInt32
+ }
+ return newSz
+}
+
// setSockOptSocket implements SetSockOpt when level is SOL_SOCKET.
func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name int, optVal []byte) *syserr.Error {
switch name {
@@ -1691,7 +1713,9 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
}
v := hostarch.ByteOrder.Uint32(optVal)
- ep.SocketOptions().SetSendBufferSize(int64(v), true /* notify */)
+ min, max := ep.SocketOptions().SendBufferLimits()
+ clamped := clampBufSize(int64(v), min, max, false /* ignoreMax */)
+ ep.SocketOptions().SetSendBufferSize(clamped, true /* notify */)
return nil
case linux.SO_RCVBUF:
@@ -1700,7 +1724,24 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
}
v := hostarch.ByteOrder.Uint32(optVal)
- ep.SocketOptions().SetReceiveBufferSize(int64(v), true /* notify */)
+ min, max := ep.SocketOptions().ReceiveBufferLimits()
+ clamped := clampBufSize(int64(v), min, max, false /* ignoreMax */)
+ ep.SocketOptions().SetReceiveBufferSize(clamped, true /* notify */)
+ return nil
+
+ case linux.SO_RCVBUFFORCE:
+ if len(optVal) < sizeOfInt32 {
+ return syserr.ErrInvalidArgument
+ }
+
+ if creds := auth.CredentialsFromContext(t); !creds.HasCapability(linux.CAP_NET_ADMIN) {
+ return syserr.ErrNotPermitted
+ }
+
+ v := hostarch.ByteOrder.Uint32(optVal)
+ min, max := ep.SocketOptions().ReceiveBufferLimits()
+ clamped := clampBufSize(int64(v), min, max, true /* ignoreMax */)
+ ep.SocketOptions().SetReceiveBufferSize(clamped, true /* notify */)
return nil
case linux.SO_REUSEADDR:
@@ -3016,7 +3057,7 @@ func Ioctl(ctx context.Context, ep commonEndpoint, io usermem.IO, args arch.Sysc
unimpl.EmitUnimplementedEvent(ctx)
}
- return 0, syserror.ENOTTY
+ return 0, linuxerr.ENOTTY
}
// interfaceIoctl implements interface requests.
diff --git a/pkg/sentry/socket/netstack/netstack_vfs2.go b/pkg/sentry/socket/netstack/netstack_vfs2.go
index 30f3ad153..edc160b1b 100644
--- a/pkg/sentry/socket/netstack/netstack_vfs2.go
+++ b/pkg/sentry/socket/netstack/netstack_vfs2.go
@@ -17,6 +17,7 @@ package netstack
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
@@ -104,7 +105,7 @@ func (s *SocketVFS2) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.
// All flags other than RWF_NOWAIT should be ignored.
// TODO(gvisor.dev/issue/2601): Support RWF_NOWAIT.
if opts.Flags != 0 {
- return 0, syserror.EOPNOTSUPP
+ return 0, linuxerr.EOPNOTSUPP
}
if dst.NumBytes() == 0 {
@@ -125,7 +126,7 @@ func (s *SocketVFS2) Write(ctx context.Context, src usermem.IOSequence, opts vfs
// All flags other than RWF_NOWAIT should be ignored.
// TODO(gvisor.dev/issue/2601): Support RWF_NOWAIT.
if opts.Flags != 0 {
- return 0, syserror.EOPNOTSUPP
+ return 0, linuxerr.EOPNOTSUPP
}
r := src.Reader(ctx)
diff --git a/pkg/sentry/socket/netstack/stack.go b/pkg/sentry/socket/netstack/stack.go
index eef5e6519..0fd0ad32c 100644
--- a/pkg/sentry/socket/netstack/stack.go
+++ b/pkg/sentry/socket/netstack/stack.go
@@ -18,10 +18,10 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/syserr"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
@@ -110,24 +110,24 @@ func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) {
switch addr.Family {
case linux.AF_INET:
if len(addr.Addr) != header.IPv4AddressSize {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
if addr.PrefixLen > header.IPv4AddressSize*8 {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
protocol = ipv4.ProtocolNumber
address = tcpip.Address(addr.Addr)
case linux.AF_INET6:
if len(addr.Addr) != header.IPv6AddressSize {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
if addr.PrefixLen > header.IPv6AddressSize*8 {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
protocol = ipv6.ProtocolNumber
address = tcpip.Address(addr.Addr)
default:
- return protocolAddress, syserror.ENOTSUP
+ return protocolAddress, linuxerr.ENOTSUP
}
protocolAddress = tcpip.ProtocolAddress{
diff --git a/pkg/sentry/socket/netstack/tun.go b/pkg/sentry/socket/netstack/tun.go
index c7ed52702..e67fe9700 100644
--- a/pkg/sentry/socket/netstack/tun.go
+++ b/pkg/sentry/socket/netstack/tun.go
@@ -16,7 +16,7 @@ package netstack
import (
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/syserror"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
)
@@ -41,7 +41,7 @@ func LinuxToTUNFlags(flags uint16) (tun.Flags, error) {
// when there is no sk_filter. See __tun_chr_ioctl() in
// net/drivers/tun.c.
if flags&^uint16(linux.IFF_TUN|linux.IFF_TAP|linux.IFF_NO_PI|linux.IFF_ONE_QUEUE) != 0 {
- return tun.Flags{}, syserror.EINVAL
+ return tun.Flags{}, linuxerr.EINVAL
}
return tun.Flags{
TUN: flags&linux.IFF_TUN != 0,