Skip to content

Commit

Permalink
Handle HTTP requests one-by-one (#238)
Browse files Browse the repository at this point in the history
By handling HTTP requests one-by-one rather than spawning a thread for
each request, an attacker can no longer force the app to create
multiple threads. It also leads to simpler code and fixes the failure
to free the memory allocated for the request.
  • Loading branch information
killenheladagen authored Apr 25, 2024
1 parent aaf835e commit 1b71543
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 21 deletions.
24 changes: 8 additions & 16 deletions app/fcgi_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,16 @@ struct request_context {
static void* handle_fcgi(void* request_context_void_ptr) {
g_autofree struct request_context* request_context =
(struct request_context*)request_context_void_ptr;
GThreadPool* workers = g_thread_pool_new((GFunc)request_context->callback,
request_context->parameter,
-1,
FALSE,
NULL);
while (workers) {
FCGX_Request* request = g_malloc0(sizeof(FCGX_Request));
FCGX_InitRequest(request, g_socket, FCGI_FAIL_ACCEPT_ON_INTR);
if (FCGX_Accept_r(request) < 0) {
log_info("FCGX_Accept_r: %s", strerror(errno));
g_free(request);
break;
while (true) {
FCGX_Request request = {};
FCGX_InitRequest(&request, g_socket, FCGI_FAIL_ACCEPT_ON_INTR);
if (FCGX_Accept_r(&request) < 0) {
// shutdown() was called on g_socket, which causes FCGX_Accept_r() to fail.
log_debug("Stopping FCGI server, because FCGX_Accept_r() returned %s", strerror(errno));
return NULL;
}
g_thread_pool_push(workers, request, NULL);
request_context->callback(&request, request_context->parameter);
}
log_info("Stopping FCGI server");
g_thread_pool_free(workers, true, false);
return NULL;
}

int fcgi_start(fcgi_request_callback request_callback, void* request_callback_parameter) {
Expand Down
3 changes: 2 additions & 1 deletion app/fcgi_server.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <fcgiapp.h>

typedef void (*fcgi_request_callback)(void* request_void_ptr, void* userdata);
typedef void (*fcgi_request_callback)(FCGX_Request* request, void* userdata);

int fcgi_start(fcgi_request_callback request_callback, void* request_callback_parameter);
void fcgi_stop(void);
4 changes: 1 addition & 3 deletions app/http_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@ static void malformed_request(FCGX_Request* request, const char* method, const c
response_msg(request, HTTP_400_BAD_REQUEST, "Malformed request");
}

void http_request_callback(void* request_void_ptr, void* restart_dockerd_context_void_ptr) {
FCGX_Request* request = (FCGX_Request*)request_void_ptr;

void http_request_callback(FCGX_Request* request, void* restart_dockerd_context_void_ptr) {
const char* method = FCGX_GetParam("REQUEST_METHOD", request->envp);
const char* uri = FCGX_GetParam("REQUEST_URI", request->envp);

Expand Down
3 changes: 2 additions & 1 deletion app/http_request.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include <fcgiapp.h>

struct app_state;

Expand All @@ -10,4 +11,4 @@ struct restart_dockerd_context {
};

// Callback function called from a thread by the FCGI server
void http_request_callback(void* request_void_ptr, void* restart_dockerd_context_void_ptr);
void http_request_callback(FCGX_Request* request, void* restart_dockerd_context_void_ptr);

0 comments on commit 1b71543

Please sign in to comment.