[icinga-checkins] icinga.org: icinga2/fix/process-spawn-buf-13655: Pass length over socket to allow for up to 1MB of json status when spawning process

git at icinga.org git at icinga.org
Thu Jan 12 09:42:17 CET 2017


Module: icinga2
Branch: fix/process-spawn-buf-13655
Commit: 538004fcc4b1c4e954621c7b62138d3dac032172
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=538004fcc4b1c4e954621c7b62138d3dac032172

Author: Lucas Fairchild-Madar <lucas.madar at gmail.com>
Date:   Fri Jan  6 12:52:25 2017 -0800

Pass length over socket to allow for up to 1MB of json status when spawning process

Signed-off-by: Michael Friedrich <michael.friedrich at icinga.com>

---

 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 8fcf37c..e93a302 100644
--- a/lib/base/process.cpp
+++ b/lib/base/process.cpp
@@ -250,13 +250,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;
@@ -267,14 +268,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);
 
@@ -351,6 +383,7 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
 	request->Set("extraEnvironment", extraEnvironment);
 
 	String jrequest = JsonEncode(request);
+	size_t length = jrequest.GetLength();
 
 	boost::mutex::scoped_lock lock(l_ProcessControlMutex);
 
@@ -358,8 +391,8 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
 	memset(&msg, 0, sizeof(msg));
 
 	struct iovec io;
-	io.iov_base = const_cast<char *>(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;
@@ -380,6 +413,12 @@ static pid_t ProcessSpawn(const std::vector<String>& 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);
@@ -401,12 +440,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);
@@ -427,12 +473,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);
@@ -712,7 +765,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;
 



More information about the icinga-checkins mailing list