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 <michael.friedrich@icinga.com>
This commit is contained in:
Lucas Fairchild-Madar 2017-01-06 12:52:25 -08:00 committed by Gunnar Beutner
parent b91aedaf19
commit 9fa3f3b122
1 changed files with 66 additions and 13 deletions

View File

@ -249,13 +249,14 @@ static void ProcessHandler(void)
} }
for (;;) { for (;;) {
size_t length;
struct msghdr msg; struct msghdr msg;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
char mbuf[4096];
struct iovec io; struct iovec io;
io.iov_base = mbuf; io.iov_base = &length;
io.iov_len = sizeof(mbuf); io.iov_len = sizeof(size_t);
msg.msg_iov = &io; msg.msg_iov = &io;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
@ -266,14 +267,45 @@ static void ProcessHandler(void)
int rc = recvmsg(l_ProcessControlFD, &msg, 0); 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; 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;
delete [] mbuf;
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("recv")
<< boost::errinfo_errno(errno));
}
count += rc;
if (rc == 0)
break; break;
} }
String jrequest = String(mbuf, mbuf + rc); String jrequest = String(mbuf, mbuf + count);
delete [] mbuf;
Dictionary::Ptr request = JsonDecode(jrequest); Dictionary::Ptr request = JsonDecode(jrequest);
@ -350,6 +382,7 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
request->Set("extraEnvironment", extraEnvironment); request->Set("extraEnvironment", extraEnvironment);
String jrequest = JsonEncode(request); String jrequest = JsonEncode(request);
size_t length = jrequest.GetLength();
boost::mutex::scoped_lock lock(l_ProcessControlMutex); boost::mutex::scoped_lock lock(l_ProcessControlMutex);
@ -357,8 +390,8 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
struct iovec io; struct iovec io;
io.iov_base = const_cast<char *>(jrequest.CStr()); io.iov_base = &length;
io.iov_len = jrequest.GetLength(); io.iov_len = sizeof(size_t);
msg.msg_iov = &io; msg.msg_iov = &io;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
@ -379,6 +412,12 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
while (sendmsg(l_ProcessControlFD, &msg, 0) < 0) while (sendmsg(l_ProcessControlFD, &msg, 0) < 0)
StartSpawnProcessHelper(); 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]; char buf[4096];
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0); 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); request->Set("signum", signum);
String jrequest = JsonEncode(request); String jrequest = JsonEncode(request);
size_t length = jrequest.GetLength();
boost::mutex::scoped_lock lock(l_ProcessControlMutex); 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(); 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]; char buf[4096];
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0); 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); request->Set("pid", pid);
String jrequest = JsonEncode(request); String jrequest = JsonEncode(request);
size_t length = jrequest.GetLength();
boost::mutex::scoped_lock lock(l_ProcessControlMutex); 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(); 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]; char buf[4096];
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0); ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);