diff options
author | Andrei Vagin <avagin@google.com> | 2021-02-22 11:37:13 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-02-22 11:51:30 -0800 |
commit | c5a4e100085ccbd063df36706cccf93951439cb7 (patch) | |
tree | f97c68b9043fec0c37df46a94b8bf1e79fc22422 | |
parent | 19fe3a2bfb72622c307311dc61019238896a756b (diff) |
unix: sendmmsg and recvmsg have to cap a number of message to UIO_MAXIOV
Reported-by: syzbot+f2489ba0b999a45d1ad1@syzkaller.appspotmail.com
PiperOrigin-RevId: 358866218
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_socket.go | 8 | ||||
-rw-r--r-- | pkg/sentry/syscalls/linux/vfs2/socket.go | 8 | ||||
-rw-r--r-- | test/syscalls/linux/BUILD | 2 | ||||
-rw-r--r-- | test/syscalls/linux/socket_generic_test_cases.cc (renamed from test/syscalls/linux/socket_generic.cc) | 21 |
4 files changed, 38 insertions, 1 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_socket.go b/pkg/sentry/syscalls/linux/sys_socket.go index 686392cc8..c6adfe06b 100644 --- a/pkg/sentry/syscalls/linux/sys_socket.go +++ b/pkg/sentry/syscalls/linux/sys_socket.go @@ -657,6 +657,10 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc return 0, nil, syserror.EINVAL } + if vlen > linux.UIO_MAXIOV { + vlen = linux.UIO_MAXIOV + } + // Reject flags that we don't handle yet. if flags & ^(baseRecvFlags|linux.MSG_CMSG_CLOEXEC|linux.MSG_ERRQUEUE) != 0 { return 0, nil, syserror.EINVAL @@ -938,6 +942,10 @@ func SendMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc return 0, nil, syserror.EINVAL } + if vlen > linux.UIO_MAXIOV { + vlen = linux.UIO_MAXIOV + } + // Get socket from the file descriptor. file := t.GetFile(fd) if file == nil { diff --git a/pkg/sentry/syscalls/linux/vfs2/socket.go b/pkg/sentry/syscalls/linux/vfs2/socket.go index 7636ca453..346fd1cea 100644 --- a/pkg/sentry/syscalls/linux/vfs2/socket.go +++ b/pkg/sentry/syscalls/linux/vfs2/socket.go @@ -660,6 +660,10 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc return 0, nil, syserror.EINVAL } + if vlen > linux.UIO_MAXIOV { + vlen = linux.UIO_MAXIOV + } + // Reject flags that we don't handle yet. if flags & ^(baseRecvFlags|linux.MSG_CMSG_CLOEXEC|linux.MSG_ERRQUEUE) != 0 { return 0, nil, syserror.EINVAL @@ -941,6 +945,10 @@ func SendMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc return 0, nil, syserror.EINVAL } + if vlen > linux.UIO_MAXIOV { + vlen = linux.UIO_MAXIOV + } + // Get socket from the file descriptor. file := t.GetFileVFS2(fd) if file == nil { diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index 31dc2525c..1a492bca3 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -2305,7 +2305,7 @@ cc_library( name = "socket_generic_test_cases", testonly = 1, srcs = [ - "socket_generic.cc", + "socket_generic_test_cases.cc", ], hdrs = [ "socket_generic.h", diff --git a/test/syscalls/linux/socket_generic.cc b/test/syscalls/linux/socket_generic_test_cases.cc index f70047a09..5c4cb6c35 100644 --- a/test/syscalls/linux/socket_generic.cc +++ b/test/syscalls/linux/socket_generic_test_cases.cc @@ -98,6 +98,27 @@ TEST_P(AllSocketPairTest, BasicSendmmsg) { EXPECT_EQ(0, memcmp(sent_data, received_data, sizeof(sent_data))); } +TEST_P(AllSocketPairTest, SendmmsgIsLimitedByMAXIOV) { + std::unique_ptr<SocketPair> sockets = + ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + char c = 0; + + std::vector<struct mmsghdr> msgs(UIO_MAXIOV + 1); + std::vector<struct iovec> iovs(msgs.size()); + for (size_t i = 0; i < msgs.size(); i++) { + iovs[i].iov_len = 1; + iovs[i].iov_base = &c; + msgs[i].msg_hdr.msg_iov = &iovs[i]; + msgs[i].msg_hdr.msg_iovlen = 1; + } + + int n; + ASSERT_THAT(n = RetryEINTR(sendmmsg)(sockets->first_fd(), msgs.data(), + msgs.size(), MSG_DONTWAIT), + SyscallSucceeds()); + EXPECT_LE(n, UIO_MAXIOV); +} + TEST_P(AllSocketPairTest, BasicRecvmmsg) { auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); char sent_data[200]; |