From 9fa3f3b1221efc487763923d95c5bde0ccbc60b1 Mon Sep 17 00:00:00 2001 From: Lucas Fairchild-Madar Date: Fri, 6 Jan 2017 12:52:25 -0800 Subject: [PATCH] Fix crash when sending/receiving messages longer than 4 kB to/from the child process for the Process class refs #13655 Signed-off-by: Michael Friedrich --- lib/base/process.cpp | 77 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/lib/base/process.cpp b/lib/base/process.cpp index d5db747bf..dba033208 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -249,13 +249,14 @@ static void ProcessHandler(void) } for (;;) { + size_t length; + struct msghdr msg; memset(&msg, 0, sizeof(msg)); - char mbuf[4096]; struct iovec io; - io.iov_base = mbuf; - io.iov_len = sizeof(mbuf); + io.iov_base = &length; + io.iov_len = sizeof(size_t); msg.msg_iov = &io; msg.msg_iovlen = 1; @@ -266,14 +267,45 @@ static void ProcessHandler(void) int rc = recvmsg(l_ProcessControlFD, &msg, 0); - if (rc <= 0) { - if (rc < 0 && (errno == EINTR || errno == EAGAIN)) + if (rc < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + + if (rc < 0) { + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("recvmsg") + << boost::errinfo_errno(errno)); + } + + if (length > 1024 * 1024 * 1024) { + BOOST_THROW_EXCEPTION(std::runtime_error("invalid message length")); + } + + char *mbuf = new char[length]; + + size_t count = 0; + while (count < length) { + rc = recv(l_ProcessControlFD, mbuf + count, length - count, 0); + + if (rc < 0) { + if (errno == EINTR || errno == EAGAIN) continue; - break; + delete [] mbuf; + + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("recv") + << boost::errinfo_errno(errno)); + } + + count += rc; + + if (rc == 0) + break; } - String jrequest = String(mbuf, mbuf + rc); + String jrequest = String(mbuf, mbuf + count); + + delete [] mbuf; Dictionary::Ptr request = JsonDecode(jrequest); @@ -350,6 +382,7 @@ static pid_t ProcessSpawn(const std::vector& arguments, const Dictionary request->Set("extraEnvironment", extraEnvironment); String jrequest = JsonEncode(request); + size_t length = jrequest.GetLength(); boost::mutex::scoped_lock lock(l_ProcessControlMutex); @@ -357,8 +390,8 @@ static pid_t ProcessSpawn(const std::vector& arguments, const Dictionary memset(&msg, 0, sizeof(msg)); struct iovec io; - io.iov_base = const_cast(jrequest.CStr()); - io.iov_len = jrequest.GetLength(); + io.iov_base = &length; + io.iov_len = sizeof(size_t); msg.msg_iov = &io; msg.msg_iovlen = 1; @@ -379,6 +412,12 @@ static pid_t ProcessSpawn(const std::vector& arguments, const Dictionary while (sendmsg(l_ProcessControlFD, &msg, 0) < 0) StartSpawnProcessHelper(); + if (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0) { + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("send") + << boost::errinfo_errno(errno)); + } + char buf[4096]; ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0); @@ -400,12 +439,19 @@ static int ProcessKill(pid_t pid, int signum) request->Set("signum", signum); String jrequest = JsonEncode(request); + size_t length = jrequest.GetLength(); boost::mutex::scoped_lock lock(l_ProcessControlMutex); - while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0) + while (send(l_ProcessControlFD, &length, sizeof(size_t), 0) < 0) StartSpawnProcessHelper(); + if (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0) { + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("send") + << boost::errinfo_errno(errno)); + } + char buf[4096]; ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0); @@ -426,12 +472,19 @@ static int ProcessWaitPID(pid_t pid, int *status) request->Set("pid", pid); String jrequest = JsonEncode(request); + size_t length = jrequest.GetLength(); boost::mutex::scoped_lock lock(l_ProcessControlMutex); - while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0) + while (send(l_ProcessControlFD, &length, sizeof(size_t), 0) < 0) StartSpawnProcessHelper(); + if (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0) { + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("send") + << boost::errinfo_errno(errno)); + } + char buf[4096]; ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0); @@ -711,7 +764,7 @@ static BOOL CreatePipeOverlapped(HANDLE *outReadPipe, HANDLE *outWritePipe, *outReadPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_INBOUND | readMode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size, 60 * 1000, securityAttributes); - + if (*outReadPipe == INVALID_HANDLE_VALUE) return FALSE; -- 2.49.0