From 79f4110365fe85f4377c50f0893134a8d5e45575 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Fri, 30 Oct 2026 01:00:52 +0100 Subject: Consolidate all tcp/http tear down into a single http_close function to prevent a rare UAF for expiring connections --- ot_http.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'ot_http.c') diff --git a/ot_http.c b/ot_http.c index 927d618..c2f7e5e 100644 --- a/ot_http.c +++ b/ot_http.c @@ -38,12 +38,34 @@ ssize_t g_stats_path_len; enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; +/* Give up a connection: the one place that knows everything hanging off it. + The slot is released before anything is freed, so that a late event or the + expiry sweep finds a closed descriptor rather than a freed cookie. */ +void http_close(const int64_t sock) { + struct http_data *cookie = fdstate_cookie(sock); + + fdstate_close((int)sock); + + if (cookie) { + if (cookie->batch) + batch_reset(cookie->batch); + free(cookie->batch); + buf_reset(&cookie->request); + if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) + mutex_workqueue_canceltask(sock); + free(cookie); + } + + event_del((int)sock); + close((int)sock); +} + static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { struct http_data *cookie = fdstate_cookie(sock); ssize_t written_size; if (!cookie) { - event_del((int)sock), close((int)sock); + http_close(sock); return; } @@ -65,9 +87,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { written_size = write(sock, ws->reply, ws->reply_size); if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { - buf_reset(&cookie->request); - free(cookie); - event_del((int)sock), close((int)sock); + http_close(sock); return; } @@ -75,9 +95,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { char *outbuf; if (!(outbuf = malloc(ws->reply_size - written_size))) { - buf_reset(&cookie->request); - free(cookie); - event_del((int)sock), close((int)sock); + http_close(sock); return; } @@ -86,9 +104,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { cookie->batch = calloc(1, sizeof(ot_batch)); if (!cookie->batch) { free(outbuf); - buf_reset(&cookie->request); - free(cookie); - event_del((int)sock), close((int)sock); + http_close(sock); return; } } -- cgit v1.3