diff options
Diffstat (limited to 'meta-webserver/recipes-httpd/monkey')
| -rw-r--r-- | meta-webserver/recipes-httpd/monkey/files/0001-server-http-fix-malformed-request-crash-paths.patch | 160 | ||||
| -rw-r--r-- | meta-webserver/recipes-httpd/monkey/files/0002-server-scheduler-guard-protocol-close-callback.patch | 51 | ||||
| -rw-r--r-- | meta-webserver/recipes-httpd/monkey/files/0003-server-parser-harden-boundary-checks.patch | 108 | ||||
| -rw-r--r-- | meta-webserver/recipes-httpd/monkey/monkey_1.8.7.bb (renamed from meta-webserver/recipes-httpd/monkey/monkey_1.8.4.bb) | 14 |
4 files changed, 330 insertions, 3 deletions
diff --git a/meta-webserver/recipes-httpd/monkey/files/0001-server-http-fix-malformed-request-crash-paths.patch b/meta-webserver/recipes-httpd/monkey/files/0001-server-http-fix-malformed-request-crash-paths.patch new file mode 100644 index 0000000000..b57d7ac219 --- /dev/null +++ b/meta-webserver/recipes-httpd/monkey/files/0001-server-http-fix-malformed-request-crash-paths.patch | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | From 839620179e2b4e5982c53d8956d92e690d82960c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eduardo Silva <eduardo@chronosphere.io> | ||
| 3 | Date: Thu, 9 Apr 2026 12:11:52 -0600 | ||
| 4 | Subject: [PATCH] server: http: fix malformed request crash paths | ||
| 5 | |||
| 6 | Fix the reproducible malformed-request crash paths in the HTTP | ||
| 7 | request lifecycle. | ||
| 8 | |||
| 9 | Handle missing Host data in directory redirects, reject malformed | ||
| 10 | range delimiters before substring parsing, and avoid reusing invalid | ||
| 11 | request state while advancing pipelined requests. | ||
| 12 | |||
| 13 | Verified by rebuilding with cmake --build build and replaying the | ||
| 14 | reported crash-inducing request fixtures against build/bin/monkey. | ||
| 15 | |||
| 16 | Signed-off-by: Eduardo Silva <eduardo@chronosphere.io> | ||
| 17 | |||
| 18 | This patch is part of https://github.com/monkey/monkey/pull/434, | ||
| 19 | containing assorted CVE fixes. | ||
| 20 | |||
| 21 | Upstream-Status: Backport [https://github.com/monkey/monkey/commit/1570f41231888ae8c7fbd719704e2486a952e45d] | ||
| 22 | Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> | ||
| 23 | --- | ||
| 24 | mk_core/mk_memory.c | 10 ++++++++++ | ||
| 25 | mk_server/mk_http.c | 46 +++++++++++++++++++++++++++++++++++++++++---- | ||
| 26 | 2 files changed, 52 insertions(+), 4 deletions(-) | ||
| 27 | |||
| 28 | diff --git a/mk_core/mk_memory.c b/mk_core/mk_memory.c | ||
| 29 | index c4073e23..008f7ac6 100644 | ||
| 30 | --- a/mk_core/mk_memory.c | ||
| 31 | +++ b/mk_core/mk_memory.c | ||
| 32 | @@ -52,6 +52,16 @@ char *mk_ptr_to_buf(mk_ptr_t p) | ||
| 33 | { | ||
| 34 | char *buf; | ||
| 35 | |||
| 36 | + if (!p.data || p.len == 0) { | ||
| 37 | + buf = mk_mem_alloc(1); | ||
| 38 | + if (!buf) { | ||
| 39 | + return NULL; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + buf[0] = '\0'; | ||
| 43 | + return buf; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | buf = mk_mem_alloc(p.len + 1); | ||
| 47 | if (!buf) return NULL; | ||
| 48 | |||
| 49 | diff --git a/mk_server/mk_http.c b/mk_server/mk_http.c | ||
| 50 | index ad12a74a..f2f12554 100644 | ||
| 51 | --- a/mk_server/mk_http.c | ||
| 52 | +++ b/mk_server/mk_http.c | ||
| 53 | @@ -457,6 +457,10 @@ static int mk_http_range_parse(struct mk_http_request *sr) | ||
| 54 | if ((sep_pos = mk_string_char_search(sr->range.data, '-', sr->range.len)) < 0) | ||
| 55 | return -1; | ||
| 56 | |||
| 57 | + if (sep_pos < eq_pos) { | ||
| 58 | + return -1; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | len = sr->range.len; | ||
| 62 | sh = &sr->headers; | ||
| 63 | |||
| 64 | @@ -476,10 +480,16 @@ static int mk_http_range_parse(struct mk_http_request *sr) | ||
| 65 | /* =yyy-xxx */ | ||
| 66 | if ((eq_pos + 1 != sep_pos) && (len > sep_pos + 1)) { | ||
| 67 | buffer = mk_string_copy_substr(sr->range.data, eq_pos + 1, sep_pos); | ||
| 68 | + if (!buffer) { | ||
| 69 | + return -1; | ||
| 70 | + } | ||
| 71 | sh->ranges[0] = (unsigned long) atol(buffer); | ||
| 72 | mk_mem_free(buffer); | ||
| 73 | |||
| 74 | buffer = mk_string_copy_substr(sr->range.data, sep_pos + 1, len); | ||
| 75 | + if (!buffer) { | ||
| 76 | + return -1; | ||
| 77 | + } | ||
| 78 | sh->ranges[1] = (unsigned long) atol(buffer); | ||
| 79 | mk_mem_free(buffer); | ||
| 80 | |||
| 81 | @@ -493,6 +503,9 @@ static int mk_http_range_parse(struct mk_http_request *sr) | ||
| 82 | /* =yyy- */ | ||
| 83 | if ((eq_pos + 1 != sep_pos) && (len == sep_pos + 1)) { | ||
| 84 | buffer = mk_string_copy_substr(sr->range.data, eq_pos + 1, len); | ||
| 85 | + if (!buffer) { | ||
| 86 | + return -1; | ||
| 87 | + } | ||
| 88 | sr->headers.ranges[0] = (unsigned long) atol(buffer); | ||
| 89 | mk_mem_free(buffer); | ||
| 90 | |||
| 91 | @@ -522,7 +535,16 @@ static int mk_http_directory_redirect_check(struct mk_http_session *cs, | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | + if (!sr->host.data || sr->host.len <= 0) { | ||
| 96 | + mk_http_error(MK_CLIENT_BAD_REQUEST, cs, sr, server); | ||
| 97 | + return -1; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | host = mk_ptr_to_buf(sr->host); | ||
| 101 | + if (!host) { | ||
| 102 | + mk_http_error(MK_CLIENT_BAD_REQUEST, cs, sr, server); | ||
| 103 | + return -1; | ||
| 104 | + } | ||
| 105 | |||
| 106 | /* | ||
| 107 | * Add ending slash to the location string | ||
| 108 | @@ -588,6 +610,9 @@ static inline char *mk_http_index_lookup(mk_ptr_t *path_base, | ||
| 109 | } | ||
| 110 | |||
| 111 | off = path_base->len; | ||
| 112 | + if ((size_t) off >= buf_size) { | ||
| 113 | + return NULL; | ||
| 114 | + } | ||
| 115 | memcpy(buf, path_base->data, off); | ||
| 116 | |||
| 117 | mk_list_foreach(head, server->index_files) { | ||
| 118 | @@ -1138,15 +1163,27 @@ int mk_http_request_end(struct mk_http_session *cs, struct mk_server *server) | ||
| 119 | ret = mk_http_parser_more(&cs->parser, cs->body_length); | ||
| 120 | if (ret == MK_TRUE) { | ||
| 121 | /* Our pipeline request limit is the same that our keepalive limit */ | ||
| 122 | + if (cs->parser.i < 0 || | ||
| 123 | + (unsigned int) (cs->parser.i + 1) >= cs->body_length) { | ||
| 124 | + goto shutdown; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | cs->counter_connections++; | ||
| 128 | len = (cs->body_length - cs->parser.i) -1; | ||
| 129 | + if (len <= 0) { | ||
| 130 | + goto shutdown; | ||
| 131 | + } | ||
| 132 | memmove(cs->body, | ||
| 133 | cs->body + cs->parser.i + 1, | ||
| 134 | len); | ||
| 135 | cs->body_length = len; | ||
| 136 | |||
| 137 | /* Prepare for next one */ | ||
| 138 | - sr = mk_list_entry_first(&cs->request_list, struct mk_http_request, _head); | ||
| 139 | + if (mk_list_is_empty(&cs->request_list) == 0) { | ||
| 140 | + cs->close_now = MK_TRUE; | ||
| 141 | + goto shutdown; | ||
| 142 | + } | ||
| 143 | + sr = &cs->sr_fixed; | ||
| 144 | mk_http_request_free(sr, server); | ||
| 145 | mk_http_request_init(cs, sr, server); | ||
| 146 | mk_http_parser_init(&cs->parser); | ||
| 147 | @@ -1626,9 +1663,10 @@ int mk_http_sched_done(struct mk_sched_conn *conn, | ||
| 148 | struct mk_http_request *sr; | ||
| 149 | |||
| 150 | session = mk_http_session_get(conn); | ||
| 151 | - sr = mk_list_entry_first(&session->request_list, | ||
| 152 | - struct mk_http_request, _head); | ||
| 153 | - mk_plugin_stage_run_40(session, sr, server); | ||
| 154 | + if (mk_list_is_empty(&session->request_list) != 0) { | ||
| 155 | + sr = &session->sr_fixed; | ||
| 156 | + mk_plugin_stage_run_40(session, sr, server); | ||
| 157 | + } | ||
| 158 | |||
| 159 | return mk_http_request_end(session, server); | ||
| 160 | } | ||
diff --git a/meta-webserver/recipes-httpd/monkey/files/0002-server-scheduler-guard-protocol-close-callback.patch b/meta-webserver/recipes-httpd/monkey/files/0002-server-scheduler-guard-protocol-close-callback.patch new file mode 100644 index 0000000000..c731db0919 --- /dev/null +++ b/meta-webserver/recipes-httpd/monkey/files/0002-server-scheduler-guard-protocol-close-callback.patch | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | From 82fb537e74e9b801d196b76efaf735ee50cd86c6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eduardo Silva <eduardo@chronosphere.io> | ||
| 3 | Date: Thu, 9 Apr 2026 12:43:31 -0600 | ||
| 4 | Subject: [PATCH] server: scheduler: guard protocol close callback | ||
| 5 | |||
| 6 | Avoid calling a null cb_close handler from the scheduler close | ||
| 7 | and timeout paths. | ||
| 8 | |||
| 9 | This fixes the HTTP/2 upgrade case where the protocol handler can be | ||
| 10 | switched to mk_http2_handler even though that handler does not | ||
| 11 | implement cb_close. | ||
| 12 | |||
| 13 | Verified by rebuilding with cmake --build build. | ||
| 14 | |||
| 15 | Signed-off-by: Eduardo Silva <eduardo@chronosphere.io> | ||
| 16 | |||
| 17 | This patch is part of https://github.com/monkey/monkey/pull/434, | ||
| 18 | containing assorted CVE fixes. | ||
| 19 | |||
| 20 | Upstream-Status: Backport [https://github.com/monkey/monkey/commit/fc1d68fb38044df08cb43c7d9af0f68714388efc] | ||
| 21 | Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> | ||
| 22 | --- | ||
| 23 | mk_server/mk_scheduler.c | 8 +++++--- | ||
| 24 | 1 file changed, 5 insertions(+), 3 deletions(-) | ||
| 25 | |||
| 26 | diff --git a/mk_server/mk_scheduler.c b/mk_server/mk_scheduler.c | ||
| 27 | index a680d3cd..3cf0ba40 100644 | ||
| 28 | --- a/mk_server/mk_scheduler.c | ||
| 29 | +++ b/mk_server/mk_scheduler.c | ||
| 30 | @@ -598,8 +598,10 @@ int mk_sched_check_timeouts(struct mk_sched_worker *sched, | ||
| 31 | MK_TRACE("Scheduler, closing fd %i due TIMEOUT", | ||
| 32 | conn->event.fd); | ||
| 33 | MK_LT_SCHED(conn->event.fd, "TIMEOUT_CONN_PENDING"); | ||
| 34 | - conn->protocol->cb_close(conn, sched, MK_SCHED_CONN_TIMEOUT, | ||
| 35 | - server); | ||
| 36 | + if (conn->protocol->cb_close) { | ||
| 37 | + conn->protocol->cb_close(conn, sched, MK_SCHED_CONN_TIMEOUT, | ||
| 38 | + server); | ||
| 39 | + } | ||
| 40 | mk_sched_drop_connection(conn, sched, server); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | @@ -749,7 +751,7 @@ int mk_sched_event_close(struct mk_sched_conn *conn, | ||
| 44 | MK_TRACE("[FD %i] Connection Handler, closed", conn->event.fd); | ||
| 45 | mk_event_del(sched->loop, &conn->event); | ||
| 46 | |||
| 47 | - if (type != MK_EP_SOCKET_DONE) { | ||
| 48 | + if (type != MK_EP_SOCKET_DONE && conn->protocol->cb_close) { | ||
| 49 | conn->protocol->cb_close(conn, sched, type, server); | ||
| 50 | } | ||
| 51 | /* | ||
diff --git a/meta-webserver/recipes-httpd/monkey/files/0003-server-parser-harden-boundary-checks.patch b/meta-webserver/recipes-httpd/monkey/files/0003-server-parser-harden-boundary-checks.patch new file mode 100644 index 0000000000..1e56893c65 --- /dev/null +++ b/meta-webserver/recipes-httpd/monkey/files/0003-server-parser-harden-boundary-checks.patch | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | From b9f24a2968fa62de4a6ecf070fa0389ce10e7729 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eduardo Silva <eduardo@chronosphere.io> | ||
| 3 | Date: Thu, 9 Apr 2026 12:11:57 -0600 | ||
| 4 | Subject: [PATCH] server: parser: harden boundary checks | ||
| 5 | |||
| 6 | Tighten parser and helper validation around explicit lengths and | ||
| 7 | buffer boundaries. | ||
| 8 | |||
| 9 | Require exact header literal matches, validate chunk length tokens, | ||
| 10 | and guard helper routines that previously trusted inconsistent | ||
| 11 | pointer or length state. | ||
| 12 | |||
| 13 | Verified by rebuilding with cmake --build build and replaying the | ||
| 14 | reported malformed request fixtures against build/bin/monkey. | ||
| 15 | |||
| 16 | Signed-off-by: Eduardo Silva <eduardo@chronosphere.io> | ||
| 17 | |||
| 18 | This patch is part of https://github.com/monkey/monkey/pull/434, | ||
| 19 | containing assorted CVE fixes. | ||
| 20 | |||
| 21 | Upstream-Status: Backport [https://github.com/monkey/monkey/commit/ffe0d0ed1b074ea6f3965c37bb754e9f19130a82] | ||
| 22 | Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> | ||
| 23 | --- | ||
| 24 | include/monkey/mk_http_parser.h | 6 +++++- | ||
| 25 | mk_server/mk_http_parser.c | 13 +++++++++++++ | ||
| 26 | mk_server/mk_mimetype.c | 7 ++++++- | ||
| 27 | mk_server/mk_user.c | 2 +- | ||
| 28 | 4 files changed, 25 insertions(+), 3 deletions(-) | ||
| 29 | |||
| 30 | diff --git a/include/monkey/mk_http_parser.h b/include/monkey/mk_http_parser.h | ||
| 31 | index 9e3b365e..465ea0e4 100644 | ||
| 32 | --- a/include/monkey/mk_http_parser.h | ||
| 33 | +++ b/include/monkey/mk_http_parser.h | ||
| 34 | @@ -389,7 +389,11 @@ int mk_http_parser_chunked_decode_buf(struct mk_http_parser *p, | ||
| 35 | |||
| 36 | static inline int mk_http_parser_more(struct mk_http_parser *p, int len) | ||
| 37 | { | ||
| 38 | - if (abs(len - p->i) - 1 > 0) { | ||
| 39 | + if (len <= 0 || p->i < 0) { | ||
| 40 | + return MK_FALSE; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + if ((p->i + 1) < len) { | ||
| 44 | return MK_TRUE; | ||
| 45 | } | ||
| 46 | |||
| 47 | diff --git a/mk_server/mk_http_parser.c b/mk_server/mk_http_parser.c | ||
| 48 | index 9413528a..3c831f29 100644 | ||
| 49 | --- a/mk_server/mk_http_parser.c | ||
| 50 | +++ b/mk_server/mk_http_parser.c | ||
| 51 | @@ -173,6 +173,16 @@ static inline void request_set(mk_ptr_t *ptr, struct mk_http_parser *p, char *bu | ||
| 52 | static inline int header_cmp(const char *expected, char *value, int len) | ||
| 53 | { | ||
| 54 | int i = 0; | ||
| 55 | + size_t expected_len; | ||
| 56 | + | ||
| 57 | + if (len < 0) { | ||
| 58 | + return -1; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + expected_len = strlen(expected); | ||
| 62 | + if ((size_t) len != expected_len) { | ||
| 63 | + return -1; | ||
| 64 | + } | ||
| 65 | |||
| 66 | if (len >= 8) { | ||
| 67 | if (expected[0] != tolower(value[0])) return -1; | ||
| 68 | @@ -535,6 +545,9 @@ parse_more: | ||
| 69 | (errno != 0)) { | ||
| 70 | return MK_HTTP_PARSER_ERROR; | ||
| 71 | } | ||
| 72 | + if (ptr == tmp || *ptr != '\0') { | ||
| 73 | + return MK_HTTP_PARSER_ERROR; | ||
| 74 | + } | ||
| 75 | |||
| 76 | if (chunk_len < 0) { | ||
| 77 | return MK_HTTP_PARSER_ERROR; | ||
| 78 | diff --git a/mk_server/mk_mimetype.c b/mk_server/mk_mimetype.c | ||
| 79 | index b86b4ef1..5462ea5c 100644 | ||
| 80 | --- a/mk_server/mk_mimetype.c | ||
| 81 | +++ b/mk_server/mk_mimetype.c | ||
| 82 | @@ -197,7 +197,12 @@ struct mk_mimetype *mk_mimetype_find(struct mk_server *server, mk_ptr_t *filenam | ||
| 83 | { | ||
| 84 | int j, len; | ||
| 85 | |||
| 86 | - j = len = filename->len; | ||
| 87 | + if (!filename->data || filename->len <= 0) { | ||
| 88 | + return NULL; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + len = filename->len; | ||
| 92 | + j = len - 1; | ||
| 93 | |||
| 94 | /* looking for extension */ | ||
| 95 | while (j >= 0 && filename->data[j] != '.') { | ||
| 96 | diff --git a/mk_server/mk_user.c b/mk_server/mk_user.c | ||
| 97 | index 7200ff08..716331ac 100644 | ||
| 98 | --- a/mk_server/mk_user.c | ||
| 99 | +++ b/mk_server/mk_user.c | ||
| 100 | @@ -46,7 +46,7 @@ int mk_user_init(struct mk_http_session *cs, struct mk_http_request *sr, | ||
| 101 | } | ||
| 102 | |||
| 103 | limit = mk_string_char_search(sr->uri_processed.data + offset, '/', | ||
| 104 | - sr->uri_processed.len); | ||
| 105 | + sr->uri_processed.len - offset); | ||
| 106 | |||
| 107 | if (limit == -1) { | ||
| 108 | limit = (sr->uri_processed.len) - offset; | ||
diff --git a/meta-webserver/recipes-httpd/monkey/monkey_1.8.4.bb b/meta-webserver/recipes-httpd/monkey/monkey_1.8.7.bb index 126a2a6fa5..a9bea8f767 100644 --- a/meta-webserver/recipes-httpd/monkey/monkey_1.8.4.bb +++ b/meta-webserver/recipes-httpd/monkey/monkey_1.8.7.bb | |||
| @@ -7,13 +7,17 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=2ee41112a44fe7014dce33e26468ba93" | |||
| 7 | 7 | ||
| 8 | SECTION = "net" | 8 | SECTION = "net" |
| 9 | 9 | ||
| 10 | SRC_URI = "git://github.com/monkey/monkey;branch=master;protocol=https \ | 10 | SRC_URI = "git://github.com/monkey/monkey;branch=master;protocol=https;tag=v${PV} \ |
| 11 | file://0001-fastcgi-Use-value-instead-of-address-of-sin6_port.patch \ | 11 | file://0001-fastcgi-Use-value-instead-of-address-of-sin6_port.patch \ |
| 12 | file://0001-include-Fix-location-of-mk_core.h-etal.patch \ | 12 | file://0001-include-Fix-location-of-mk_core.h-etal.patch \ |
| 13 | file://monkey.service \ | 13 | file://monkey.service \ |
| 14 | file://monkey.init" | 14 | file://monkey.init \ |
| 15 | file://0001-server-http-fix-malformed-request-crash-paths.patch \ | ||
| 16 | file://0002-server-scheduler-guard-protocol-close-callback.patch \ | ||
| 17 | file://0003-server-parser-harden-boundary-checks.patch \ | ||
| 18 | " | ||
| 15 | 19 | ||
| 16 | SRCREV = "94af273244369e1a8426d0d1f6376475aff90db9" | 20 | SRCREV = "0fd3bbd657c6d6339315709ef068493c572b973c" |
| 17 | 21 | ||
| 18 | UPSTREAM_CHECK_COMMITS = "1" | 22 | UPSTREAM_CHECK_COMMITS = "1" |
| 19 | 23 | ||
| @@ -51,6 +55,10 @@ do_install:append() { | |||
| 51 | if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then | 55 | if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then |
| 52 | install -Dm 644 ${UNPACKDIR}/monkey.service ${D}/${systemd_unitdir}/system/monkey.service | 56 | install -Dm 644 ${UNPACKDIR}/monkey.service ${D}/${systemd_unitdir}/system/monkey.service |
| 53 | fi | 57 | fi |
| 58 | |||
| 59 | # QA Issue: monkey installs files in /var/volatile, but it is expected to be empty [empty-dirs] | ||
| 60 | # these folders are supposed to be recreated at runtime | ||
| 61 | find ${D}/var -type d -empty -delete | ||
| 54 | } | 62 | } |
| 55 | 63 | ||
| 56 | INITSCRIPT_NAME = "monkey" | 64 | INITSCRIPT_NAME = "monkey" |
