summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBhasker Hariharan <bhaskerh@google.com>2021-09-14 14:01:36 -0700
committergVisor bot <gvisor-bot@google.com>2021-09-14 14:09:09 -0700
commit603f473ada5f5cacc759c8810df01f47905ba5e9 (patch)
treedd9c05d727c494d16562f3190f2ba47fa8c3ff4f
parent5593b8a7e6cb5fc04c1b9e23a92b880517330cd4 (diff)
Fix bug in RecvMMsgDispatcher.
Fixed a bug introduced in the following commit: https://github.com/google/gvisor/commit/979d6e7d77b17e94defc29515180cc75d3560383 The commit introduced a bug which causes the recvmmsg dispatcher to never exit as BlockingPoll is now called with two fds and poll will not return an error anymore if one of the FD is closed. We need to explicitly check the events for each FD to determine if the sentry FD is closed. ReadV dispatcher does not have the same issue as Readv does not rely on sk_err field of the underlying socket to determine if the socket is in an error state. Recvmmsg OTOH seems to get confused and always returns EAGAIN if poll() is called which queries the sk_err field and clears it. PiperOrigin-RevId: 396676135
-rw-r--r--pkg/tcpip/link/rawfile/blockingpoll_amd64.s2
-rw-r--r--pkg/tcpip/link/rawfile/blockingpoll_arm64.s2
-rw-r--r--pkg/tcpip/link/rawfile/rawfile_unsafe.go16
3 files changed, 17 insertions, 3 deletions
diff --git a/pkg/tcpip/link/rawfile/blockingpoll_amd64.s b/pkg/tcpip/link/rawfile/blockingpoll_amd64.s
index 298bad55d..f2c230720 100644
--- a/pkg/tcpip/link/rawfile/blockingpoll_amd64.s
+++ b/pkg/tcpip/link/rawfile/blockingpoll_amd64.s
@@ -27,7 +27,7 @@ TEXT ·BlockingPoll(SB),NOSPLIT,$0-40
MOVQ $0x0, R10 // sigmask parameter which isn't used here
MOVQ $0x10f, AX // SYS_PPOLL
SYSCALL
- CMPQ AX, $0xfffffffffffff001
+ CMPQ AX, $0xfffffffffffff002
JLS ok
MOVQ $-1, n+24(FP)
NEGQ AX
diff --git a/pkg/tcpip/link/rawfile/blockingpoll_arm64.s b/pkg/tcpip/link/rawfile/blockingpoll_arm64.s
index b62888b93..8807586c7 100644
--- a/pkg/tcpip/link/rawfile/blockingpoll_arm64.s
+++ b/pkg/tcpip/link/rawfile/blockingpoll_arm64.s
@@ -27,7 +27,7 @@ TEXT ·BlockingPoll(SB),NOSPLIT,$0-40
MOVD $0x0, R3 // sigmask parameter which isn't used here
MOVD $0x49, R8 // SYS_PPOLL
SVC
- CMP $0xfffffffffffff001, R0
+ CMP $0xfffffffffffff002, R0
BLS ok
MOVD $-1, R1
MOVD R1, n+24(FP)
diff --git a/pkg/tcpip/link/rawfile/rawfile_unsafe.go b/pkg/tcpip/link/rawfile/rawfile_unsafe.go
index e76fc55b6..87a0b9a62 100644
--- a/pkg/tcpip/link/rawfile/rawfile_unsafe.go
+++ b/pkg/tcpip/link/rawfile/rawfile_unsafe.go
@@ -181,7 +181,9 @@ func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, tcpip
if e == 0 {
return int(n), nil
}
-
+ if e != 0 && e != unix.EWOULDBLOCK {
+ return 0, TranslateErrno(e)
+ }
stopped, e := BlockingPollUntilStopped(efd, fd, unix.POLLIN)
if stopped {
return -1, nil
@@ -204,6 +206,10 @@ func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MMsgHdr) (int, tcpi
return int(n), nil
}
+ if e != 0 && e != unix.EWOULDBLOCK {
+ return 0, TranslateErrno(e)
+ }
+
stopped, e := BlockingPollUntilStopped(efd, fd, unix.POLLIN)
if stopped {
return -1, nil
@@ -228,5 +234,13 @@ func BlockingPollUntilStopped(efd int, fd int, events int16) (bool, unix.Errno)
},
}
_, errno := BlockingPoll(&pevents[0], len(pevents), nil)
+ if errno != 0 {
+ return pevents[0].Revents&unix.POLLIN != 0, errno
+ }
+
+ if pevents[1].Revents&unix.POLLHUP != 0 || pevents[1].Revents&unix.POLLERR != 0 {
+ errno = unix.ECONNRESET
+ }
+
return pevents[0].Revents&unix.POLLIN != 0, errno
}