From c0a12f594ba2a873ffd5ec8974c5582e6283fbdf Mon Sep 17 00:00:00 2001 From: Reid Linnemann Date: Mon, 5 Feb 2024 11:12:56 -0700 Subject: [PATCH] sysutils/check_reload_status: Handle socket closure correctly. Fixes #14386 In adverse conditions it is possible that php-fpm can actually close a connection from an instance of fcgi-cli and not send a respone at all. This was not handled correctly by the recv loops, which did not recognize the return value 0 on the blocking socket as a closed socket condition. If php-fpm closes the socket prematurely because it is out of resources or hits some other error condition while fcgicli is trying to read a response, this can make it loop indefinitely. Additionally, if read_packet returns a buffer but the header type is not identifiable, the program goes back into another iteration of the reading loop where again the socket may be closed and read_packet loops trying to read the eight byte header. To remedy the problem, the header and body loops are changed to recognize a recv result of 0 as an error condition and drop out returning an NULL buffer pointer. Additionally, the main program loop is changed to bail out if it receives a packet with a header type that is not recognized. --- sysutils/check_reload_status/Makefile | 2 +- sysutils/check_reload_status/files/fcgicli.c | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sysutils/check_reload_status/Makefile b/sysutils/check_reload_status/Makefile index 96fb65a38ad6..647f55a8d675 100644 --- a/sysutils/check_reload_status/Makefile +++ b/sysutils/check_reload_status/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PORTNAME= check_reload_status -PORTVERSION= 0.0.15 +PORTVERSION= 0.0.16 CATEGORIES?= sysutils MASTER_SITES= # empty DISTFILES= # none diff --git a/sysutils/check_reload_status/files/fcgicli.c b/sysutils/check_reload_status/files/fcgicli.c index bf77b9b8b1f4..e80e552b69b7 100644 --- a/sysutils/check_reload_status/files/fcgicli.c +++ b/sysutils/check_reload_status/files/fcgicli.c @@ -90,9 +90,9 @@ read_packet(FCGI_Header *header, int sockfd) while (read < len) { ssize_t r_read = recv(sockfd, header + read, len - read, 0); - if (r_read >= 0) { + if (r_read > 0) { read += r_read; - } else if (errno != EINTR){ + } else if (errno != EINTR || r_read == 0){ printf("Failed to read %zd header bytes: %s\n", (ssize_t)len - read, strerror(errno)); goto out; @@ -119,9 +119,9 @@ read_packet(FCGI_Header *header, int sockfd) read = 0; while (read < len) { ssize_t r_read = recv(sockfd, buf + read, len - read, 0); - if (r_read >= 0) { + if (r_read > 0) { read += r_read; - } else if (errno != EINTR){ + } else if (errno != EINTR || r_read == 0){ printf("Failed to read %zd payload bytes: %s\n", (ssize_t)len - read, strerror(errno)); free(buf); @@ -358,7 +358,10 @@ main(int argc, char **argv) goto endprog; break; default: - ; /*nop*/ + printf("Received unexpected header type %u, exiting", + rHeader.type); + goto endprog; + break; } } while (rHeader.type != FCGI_END_REQUEST);