fastcgi: Fix race condition when closing FastCGI connections

This commit is contained in:
2026-06-02 17:38:34 +02:00
parent dbfe0a65a5
commit dc417207a7
4 changed files with 14 additions and 15 deletions
+3 -2
View File
@@ -407,10 +407,11 @@ int sock_has_pending(sock *s, int flags) {
long sock_recv_chunk_header(sock *s) { long sock_recv_chunk_header(sock *s) {
if (s->pipe) { if (s->pipe) {
uint64_t len; int64_t len;
if (sock_recv_x(s, &len, sizeof(len), 0) == -1) if (sock_recv_x(s, &len, sizeof(len), 0) == -1)
return -1; return -1;
return (long) len; if (len < 0) errno = ECONNABORTED;
return len;
} }
long ret; long ret;
+8 -9
View File
@@ -16,7 +16,8 @@
#include <unistd.h> #include <unistd.h>
void fastcgi_frame_handler_func(fastcgi_ctx_t *ctx) { void fastcgi_frame_handler_func(fastcgi_ctx_t *ctx) {
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix); logger_set_prefix("%s", ctx->log_prefix);
int64_t val = 0;
switch (fastcgi_recv_frame(&ctx->cnx)) { switch (fastcgi_recv_frame(&ctx->cnx)) {
case FCGI_STDOUT: case FCGI_STDOUT:
@@ -25,12 +26,11 @@ void fastcgi_frame_handler_func(fastcgi_ctx_t *ctx) {
break; break;
case -1: case -1:
error("Unable to receive FastCGI frame"); error("Unable to receive FastCGI frame");
ctx->client->s_keep_alive = 0; val = -1;
fastcgi_close(ctx);
break;
default: default:
// end of request received // end of request received
write(ctx->cnx.fd_out, "\0\0\0\0\0\0\0\0\r\n", 10); write(ctx->cnx.fd_out, &val, sizeof(val));
write(ctx->cnx.fd_out, "\r\n", 2);
fastcgi_close(ctx); fastcgi_close(ctx);
} }
} }
@@ -41,7 +41,7 @@ int fastcgi_handle_connection(client_ctx_t *ctx, fastcgi_cnx_t **cnx) {
fastcgi_ctx_t *a = malloc(sizeof(fastcgi_ctx_t)); fastcgi_ctx_t *a = malloc(sizeof(fastcgi_ctx_t));
a->closed = 0; a->closed = 0;
a->client = ctx; snprintf(a->log_prefix, sizeof(a->log_prefix), "[%*s]%s", ADDRSTRLEN, ctx->socket.s_addr, ctx->log_prefix);
memcpy(&a->cnx, *cnx, sizeof(fastcgi_cnx_t)); memcpy(&a->cnx, *cnx, sizeof(fastcgi_cnx_t));
ctx->fcgi_ctx = a; ctx->fcgi_ctx = a;
fastcgi_handle_frame(a); fastcgi_handle_frame(a);
@@ -55,7 +55,7 @@ void fastcgi_close(fastcgi_ctx_t *ctx) {
if (ctx->closed != 2) if (ctx->closed != 2)
return; return;
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix); logger_set_prefix("%s", ctx->log_prefix);
fastcgi_php_error(&ctx->cnx, NULL); fastcgi_php_error(&ctx->cnx, NULL);
@@ -65,12 +65,11 @@ void fastcgi_close(fastcgi_ctx_t *ctx) {
debug("Closing FastCGI connection"); debug("Closing FastCGI connection");
fastcgi_close_cnx(&ctx->cnx); fastcgi_close_cnx(&ctx->cnx);
ctx->client->fcgi_ctx = NULL;
free(ctx); free(ctx);
errno = 0; errno = 0;
} }
void fastcgi_close_error(fastcgi_ctx_t *ctx) { void fastcgi_close_error(fastcgi_ctx_t *ctx) {
logger_set_prefix("[%*s]%s", ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix); logger_set_prefix("%s", ctx->log_prefix);
fastcgi_close_cnx(&ctx->cnx); fastcgi_close_cnx(&ctx->cnx);
} }
+2 -3
View File
@@ -31,6 +31,7 @@ void fastcgi_handler_func(client_ctx_t *ctx) {
return; return;
} else if (ctx->fcgi_ctx != NULL) { } else if (ctx->fcgi_ctx != NULL) {
fastcgi_close(ctx->fcgi_ctx); fastcgi_close(ctx->fcgi_ctx);
ctx->fcgi_ctx = NULL;
} }
} }
@@ -44,7 +45,6 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t **fcgi_cnx) {
http_uri *uri = &ctx->uri; http_uri *uri = &ctx->uri;
sock *client = &ctx->socket; sock *client = &ctx->socket;
char *err_msg = ctx->err_msg; char *err_msg = ctx->err_msg;
char buf[1024];
int mode, ret; int mode, ret;
if (strends(uri->filename, ".php")) { if (strends(uri->filename, ".php")) {
@@ -131,7 +131,7 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t **fcgi_cnx) {
res->status = &ctx->custom_status; res->status = &ctx->custom_status;
} else if (res->status == NULL) { } else if (res->status == NULL) {
res->status = http_get_status(500); res->status = http_get_status(500);
sprintf(err_msg, "The status_hdr code was set to an invalid or unknown value."); sprintf(err_msg, "The status code was set to an invalid or unknown value.");
return 2; return 2;
} }
} }
@@ -177,7 +177,6 @@ static void fastcgi_error_cb(chunk_ctx_t *ctx) {
logger_set_prefix("[%s%*s%s]%s", BLD_STR, ADDRSTRLEN, ctx->client->req_host, CLR_STR, ctx->client->log_prefix); logger_set_prefix("[%s%*s%s]%s", BLD_STR, ADDRSTRLEN, ctx->client->req_host, CLR_STR, ctx->client->log_prefix);
// FIXME segfault on error_cb
warning("Closing connection due to FastCGI error"); warning("Closing connection due to FastCGI error");
if(ctx->client->fcgi_ctx) { if(ctx->client->fcgi_ctx) {
fastcgi_close_error(ctx->client->fcgi_ctx); fastcgi_close_error(ctx->client->fcgi_ctx);
+1 -1
View File
@@ -47,7 +47,7 @@ typedef struct {
typedef struct { typedef struct {
unsigned char closed:4; unsigned char closed:4;
client_ctx_t *client; char log_prefix[128];
fastcgi_cnx_t cnx; fastcgi_cnx_t cnx;
} fastcgi_ctx_t; } fastcgi_ctx_t;