Correct hostinet receive flag handling
Accept and discard Linux-inert send-only flags on hostinet receive calls, add native and runsc syscall coverage, and bind the resulting immutable runtime build.
This commit is contained in:
parent
394fb65c86
commit
b240bc1d12
1 changed files with 88 additions and 9 deletions
74
patches/gvisor-9f8f6c917-hostinet-recv-flags.patch
Normal file
74
patches/gvisor-9f8f6c917-hostinet-recv-flags.patch
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go
|
||||
--- a/pkg/sentry/socket/hostinet/socket.go
|
||||
+++ b/pkg/sentry/socket/hostinet/socket.go
|
||||
@@ -516,7 +516,7 @@
|
||||
|
||||
func (s *Socket) recvMsgFromHost(iovs []unix.Iovec, flags int, senderRequested bool, controlLen uint64) (uint64, int, []byte, []byte, error) {
|
||||
// We always do a non-blocking recv*().
|
||||
- sysflags := flags | unix.MSG_DONTWAIT
|
||||
+ sysflags := flags&^ignoredRecvMsgFlags | unix.MSG_DONTWAIT
|
||||
|
||||
msg := unix.Msghdr{}
|
||||
if len(iovs) > 0 {
|
||||
@@ -545,13 +545,18 @@
|
||||
return n, int(msg.Flags), senderAddrBuf[:msg.Namelen], controlBuf[:msg.Controllen], err
|
||||
}
|
||||
|
||||
-const allowedRecvMsgFlags = unix.MSG_CTRUNC |
|
||||
- unix.MSG_DONTWAIT |
|
||||
- unix.MSG_ERRQUEUE |
|
||||
- unix.MSG_OOB |
|
||||
- unix.MSG_PEEK |
|
||||
- unix.MSG_TRUNC |
|
||||
- unix.MSG_WAITALL
|
||||
+const (
|
||||
+ // Linux accepts these send-only flags on receive calls and ignores them.
|
||||
+ ignoredRecvMsgFlags = unix.MSG_DONTROUTE | unix.MSG_NOSIGNAL
|
||||
+ allowedRecvMsgFlags = ignoredRecvMsgFlags |
|
||||
+ unix.MSG_CTRUNC |
|
||||
+ unix.MSG_DONTWAIT |
|
||||
+ unix.MSG_ERRQUEUE |
|
||||
+ unix.MSG_OOB |
|
||||
+ unix.MSG_PEEK |
|
||||
+ unix.MSG_TRUNC |
|
||||
+ unix.MSG_WAITALL
|
||||
+)
|
||||
|
||||
// RecvMsg implements socket.Socket.RecvMsg.
|
||||
func (s *Socket) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlLen uint64) (int, int, linux.SockAddr, uint32, socket.ControlMessages, *syserr.Error) {
|
||||
diff --git a/test/syscalls/linux/socket_ip_tcp_generic.cc b/test/syscalls/linux/socket_ip_tcp_generic.cc
|
||||
--- a/test/syscalls/linux/socket_ip_tcp_generic.cc
|
||||
+++ b/test/syscalls/linux/socket_ip_tcp_generic.cc
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "test/syscalls/linux/socket_ip_tcp_generic.h"
|
||||
|
||||
+#include <array>
|
||||
+
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
@@ -103,6 +105,23 @@
|
||||
EXPECT_GT(opt.tcpi_rto, 0);
|
||||
}
|
||||
|
||||
+TEST_P(TCPSocketPairTest, ReceiveIgnoresSendOnlyFlags) {
|
||||
+ auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
+
|
||||
+ constexpr std::array<int, 2> kFlags = {MSG_DONTROUTE, MSG_NOSIGNAL};
|
||||
+ constexpr char kPayload = 'x';
|
||||
+ for (int flags : kFlags) {
|
||||
+ ASSERT_THAT(RetryEINTR(send)(sockets->first_fd(), &kPayload,
|
||||
+ sizeof(kPayload), 0),
|
||||
+ SyscallSucceedsWithValue(sizeof(kPayload)));
|
||||
+ char received = 0;
|
||||
+ ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), &received,
|
||||
+ sizeof(received), flags),
|
||||
+ SyscallSucceedsWithValue(sizeof(received)));
|
||||
+ EXPECT_EQ(received, kPayload);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// This test validates that an RST is sent instead of a FIN when data is
|
||||
// unread on calls to close(2).
|
||||
TEST_P(TCPSocketPairTest, RSTSentOnCloseWithUnreadData) {
|
||||
Loading…
Reference in a new issue