Handle reading large messages that don't fit in a single recv().

We know the length of what we are receiving so just loop until
we have it all, get EOF or an error.
This commit is contained in:
Todd C. Miller
2021-08-31 12:09:05 -06:00
parent c0630a36c8
commit 26938012f8

View File

@@ -72,6 +72,8 @@ send_req(int sock, const uint8_t *buf, size_t len)
do { do {
nwritten = send(sock, cp, len, 0); nwritten = send(sock, cp, len, 0);
if (nwritten == -1) { if (nwritten == -1) {
if (errno == EINTR)
continue;
debug_return_bool(false); debug_return_bool(false);
} }
len -= nwritten; len -= nwritten;
@@ -129,8 +131,8 @@ recv_intercept_response(int fd)
{ {
InterceptResponse *res = NULL; InterceptResponse *res = NULL;
ssize_t nread; ssize_t nread;
uint32_t res_len; uint32_t rem, res_len;
uint8_t *buf = NULL; uint8_t *cp, *buf = NULL;
debug_decl(recv_intercept_response, SUDO_DEBUG_EXEC); debug_decl(recv_intercept_response, SUDO_DEBUG_EXEC);
/* Read message size (uint32_t in host byte order). */ /* Read message size (uint32_t in host byte order). */
@@ -155,17 +157,27 @@ recv_intercept_response(int fd)
if ((buf = malloc(res_len)) == NULL) { if ((buf = malloc(res_len)) == NULL) {
goto done; goto done;
} }
nread = recv(fd, buf, res_len, 0); cp = buf;
if ((size_t)nread != res_len) { rem = res_len;
if (nread == 0) { do {
nread = recv(fd, cp, rem, 0);
switch (nread) {
case 0:
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unexpected EOF reading response"); "unexpected EOF reading response");
} else { goto done;
case -1:
if (errno == EINTR)
continue;
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"error reading response"); "error reading response");
}
goto done; goto done;
default:
rem -= nread;
cp += nread;
break;
} }
} while (rem > 0);
res = intercept_response__unpack(NULL, res_len, buf); res = intercept_response__unpack(NULL, res_len, buf);
if (res == NULL) { if (res == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,