diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-30 01:00:52 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-30 01:00:52 +0100 |
| commit | 79f4110365fe85f4377c50f0893134a8d5e45575 (patch) | |
| tree | e69f5ceae67e4f283bede83f6649b7df0ded7076 /ot_http.c | |
| parent | d92945fe3a7960cfc7ddfd70a9a37d6db666c1e2 (diff) | |
Consolidate all tcp/http tear down into a single http_close function to prevent a rare UAF for expiring connections
Diffstat (limited to 'ot_http.c')
| -rw-r--r-- | ot_http.c | 36 |
1 files changed, 26 insertions, 10 deletions
| @@ -38,12 +38,34 @@ ssize_t g_stats_path_len; | |||
| 38 | 38 | ||
| 39 | enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; | 39 | enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; |
| 40 | 40 | ||
| 41 | /* Give up a connection: the one place that knows everything hanging off it. | ||
| 42 | The slot is released before anything is freed, so that a late event or the | ||
| 43 | expiry sweep finds a closed descriptor rather than a freed cookie. */ | ||
| 44 | void http_close(const int64_t sock) { | ||
| 45 | struct http_data *cookie = fdstate_cookie(sock); | ||
| 46 | |||
| 47 | fdstate_close((int)sock); | ||
| 48 | |||
| 49 | if (cookie) { | ||
| 50 | if (cookie->batch) | ||
| 51 | batch_reset(cookie->batch); | ||
| 52 | free(cookie->batch); | ||
| 53 | buf_reset(&cookie->request); | ||
| 54 | if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) | ||
| 55 | mutex_workqueue_canceltask(sock); | ||
| 56 | free(cookie); | ||
| 57 | } | ||
| 58 | |||
| 59 | event_del((int)sock); | ||
| 60 | close((int)sock); | ||
| 61 | } | ||
| 62 | |||
| 41 | static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | 63 | static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { |
| 42 | struct http_data *cookie = fdstate_cookie(sock); | 64 | struct http_data *cookie = fdstate_cookie(sock); |
| 43 | ssize_t written_size; | 65 | ssize_t written_size; |
| 44 | 66 | ||
| 45 | if (!cookie) { | 67 | if (!cookie) { |
| 46 | event_del((int)sock), close((int)sock); | 68 | http_close(sock); |
| 47 | return; | 69 | return; |
| 48 | } | 70 | } |
| 49 | 71 | ||
| @@ -65,9 +87,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | |||
| 65 | 87 | ||
| 66 | written_size = write(sock, ws->reply, ws->reply_size); | 88 | written_size = write(sock, ws->reply, ws->reply_size); |
| 67 | if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { | 89 | if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { |
| 68 | buf_reset(&cookie->request); | 90 | http_close(sock); |
| 69 | free(cookie); | ||
| 70 | event_del((int)sock), close((int)sock); | ||
| 71 | return; | 91 | return; |
| 72 | } | 92 | } |
| 73 | 93 | ||
| @@ -75,9 +95,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | |||
| 75 | char *outbuf; | 95 | char *outbuf; |
| 76 | 96 | ||
| 77 | if (!(outbuf = malloc(ws->reply_size - written_size))) { | 97 | if (!(outbuf = malloc(ws->reply_size - written_size))) { |
| 78 | buf_reset(&cookie->request); | 98 | http_close(sock); |
| 79 | free(cookie); | ||
| 80 | event_del((int)sock), close((int)sock); | ||
| 81 | return; | 99 | return; |
| 82 | } | 100 | } |
| 83 | 101 | ||
| @@ -86,9 +104,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { | |||
| 86 | cookie->batch = calloc(1, sizeof(ot_batch)); | 104 | cookie->batch = calloc(1, sizeof(ot_batch)); |
| 87 | if (!cookie->batch) { | 105 | if (!cookie->batch) { |
| 88 | free(outbuf); | 106 | free(outbuf); |
| 89 | buf_reset(&cookie->request); | 107 | http_close(sock); |
| 90 | free(cookie); | ||
| 91 | event_del((int)sock), close((int)sock); | ||
| 92 | return; | 108 | return; |
| 93 | } | 109 | } |
| 94 | } | 110 | } |
