diff --git a/src/sudo_intercept_common.c b/src/sudo_intercept_common.c index 0702b8c81..2a89cc64f 100644 --- a/src/sudo_intercept_common.c +++ b/src/sudo_intercept_common.c @@ -136,16 +136,29 @@ recv_intercept_response(int fd) debug_decl(recv_intercept_response, SUDO_DEBUG_EXEC); /* Read message size (uint32_t in host byte order). */ - nread = recv(fd, &res_len, sizeof(res_len), 0); - if ((size_t)nread != sizeof(res_len)) { - if (nread == 0) { + for (;;) { + nread = recv(fd, &res_len, sizeof(res_len), 0); + if (nread == ssizeof(res_len)) + break; + switch (nread) { + case 0: sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "unexpected EOF reading response size"); - } else { - sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + break; + case -1: + if (errno == EINTR) + continue; + sudo_debug_printf( + SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "error reading response size"); + break; + default: + sudo_debug_printf( + SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "error reading response size: short read"); + break; } - goto done; + goto done; } if (res_len > MESSAGE_SIZE_MAX) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, @@ -169,7 +182,8 @@ recv_intercept_response(int fd) 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"); goto done; default: @@ -199,7 +213,7 @@ sudo_interposer_init(void) { InterceptResponse *res = NULL; static bool initialized; - int fd = -1; + int flags, fd = -1; char **p; debug_decl(sudo_interposer_init, SUDO_DEBUG_EXEC); @@ -239,6 +253,13 @@ sudo_interposer_init(void) goto done; } + /* + * We don't want to use non-blocking I/O. + */ + flags = fcntl(fd, F_GETFL, 0); + if (flags != -1) + (void)fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + /* * Send InterceptHello message to over the fd. */