Fix error code returned due to Port exhaustion.

For TCP sockets gVisor incorrectly returns EAGAIN when no ephemeral ports are
available to bind during a connect. Linux returns EADDRNOTAVAIL. This change
fixes gVisor to return the correct code and adds a test for the same.

This change also fixes a minor bug for ping sockets where connect() would fail
with EINVAL unless the socket was bound first.

Also added tests for testing UDP Port exhaustion and Ping socket port
exhaustion.

PiperOrigin-RevId: 314988525
This commit is contained in:
Bhasker Hariharan
2020-06-05 13:43:01 -07:00
committed by gVisor bot
parent 45bf7492ef
commit 526df4f52a
9 changed files with 360 additions and 3 deletions
+1
View File
@@ -50,5 +50,6 @@ go_library(
"//pkg/tcpip/transport/udp",
"//pkg/usermem",
"//pkg/waiter",
"@org_golang_x_sys//unix:go_default_library",
],
)
+9
View File
@@ -33,6 +33,7 @@ import (
"syscall"
"time"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/amutex"
"gvisor.dev/gvisor/pkg/binary"
@@ -719,6 +720,14 @@ func (s *socketOpsCommon) Connect(t *kernel.Task, sockaddr []byte, blocking bool
defer s.EventUnregister(&e)
if err := s.Endpoint.Connect(addr); err != tcpip.ErrConnectStarted && err != tcpip.ErrAlreadyConnecting {
if (s.family == unix.AF_INET || s.family == unix.AF_INET6) && s.skType == linux.SOCK_STREAM {
// TCP unlike UDP returns EADDRNOTAVAIL when it can't
// find an available local ephemeral port.
if err == tcpip.ErrNoPortAvailable {
return syserr.ErrAddressNotAvailable
}
}
return syserr.TranslateNetstackError(err)
}