-
Notifications
You must be signed in to change notification settings - Fork 614
Expand file tree
/
Copy pathCVE-2025-63657.patch
More file actions
314 lines (271 loc) · 10.6 KB
/
CVE-2025-63657.patch
File metadata and controls
314 lines (271 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
From 8453990adf71d8093a42259892ac36c4f1d47e11 Mon Sep 17 00:00:00 2001
From: Eduardo Silva <eduardo@chronosphere.io>
Date: Thu, 9 Apr 2026 12:11:52 -0600
Subject: [PATCH 1/3] server: http: fix malformed request crash paths
Fix the reproducible malformed-request crash paths in the HTTP
request lifecycle.
Handle missing Host data in directory redirects, reject malformed
range delimiters before substring parsing, and avoid reusing invalid
request state while advancing pipelined requests.
Verified by rebuilding with cmake --build build and replaying the
reported crash-inducing request fixtures against build/bin/monkey.
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
---
lib/monkey/mk_core/mk_memory.c | 10 ++++++++
lib/monkey/mk_server/mk_http.c | 46 +++++++++++++++++++++++++++++++---
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/lib/monkey/mk_core/mk_memory.c b/lib/monkey/mk_core/mk_memory.c
index c4073e2..008f7ac 100644
--- a/lib/monkey/mk_core/mk_memory.c
+++ b/lib/monkey/mk_core/mk_memory.c
@@ -52,6 +52,16 @@ char *mk_ptr_to_buf(mk_ptr_t p)
{
char *buf;
+ if (!p.data || p.len == 0) {
+ buf = mk_mem_alloc(1);
+ if (!buf) {
+ return NULL;
+ }
+
+ buf[0] = '\0';
+ return buf;
+ }
+
buf = mk_mem_alloc(p.len + 1);
if (!buf) return NULL;
diff --git a/lib/monkey/mk_server/mk_http.c b/lib/monkey/mk_server/mk_http.c
index 1e2d219..3fb34e0 100644
--- a/lib/monkey/mk_server/mk_http.c
+++ b/lib/monkey/mk_server/mk_http.c
@@ -447,6 +447,10 @@ static int mk_http_range_parse(struct mk_http_request *sr)
if ((sep_pos = mk_string_char_search(sr->range.data, '-', sr->range.len)) < 0)
return -1;
+ if (sep_pos < eq_pos) {
+ return -1;
+ }
+
len = sr->range.len;
sh = &sr->headers;
@@ -466,10 +470,16 @@ static int mk_http_range_parse(struct mk_http_request *sr)
/* =yyy-xxx */
if ((eq_pos + 1 != sep_pos) && (len > sep_pos + 1)) {
buffer = mk_string_copy_substr(sr->range.data, eq_pos + 1, sep_pos);
+ if (!buffer) {
+ return -1;
+ }
sh->ranges[0] = (unsigned long) atol(buffer);
mk_mem_free(buffer);
buffer = mk_string_copy_substr(sr->range.data, sep_pos + 1, len);
+ if (!buffer) {
+ return -1;
+ }
sh->ranges[1] = (unsigned long) atol(buffer);
mk_mem_free(buffer);
@@ -483,6 +493,9 @@ static int mk_http_range_parse(struct mk_http_request *sr)
/* =yyy- */
if ((eq_pos + 1 != sep_pos) && (len == sep_pos + 1)) {
buffer = mk_string_copy_substr(sr->range.data, eq_pos + 1, len);
+ if (!buffer) {
+ return -1;
+ }
sr->headers.ranges[0] = (unsigned long) atol(buffer);
mk_mem_free(buffer);
@@ -512,7 +525,16 @@ static int mk_http_directory_redirect_check(struct mk_http_session *cs,
return 0;
}
+ if (!sr->host.data || sr->host.len <= 0) {
+ mk_http_error(MK_CLIENT_BAD_REQUEST, cs, sr, server);
+ return -1;
+ }
+
host = mk_ptr_to_buf(sr->host);
+ if (!host) {
+ mk_http_error(MK_CLIENT_BAD_REQUEST, cs, sr, server);
+ return -1;
+ }
/*
* Add ending slash to the location string
@@ -578,6 +600,9 @@ static inline char *mk_http_index_lookup(mk_ptr_t *path_base,
}
off = path_base->len;
+ if ((size_t) off >= buf_size) {
+ return NULL;
+ }
memcpy(buf, path_base->data, off);
mk_list_foreach(head, server->index_files) {
@@ -1136,15 +1161,27 @@ int mk_http_request_end(struct mk_http_session *cs, struct mk_server *server)
ret = mk_http_parser_more(&cs->parser, cs->body_length);
if (ret == MK_TRUE) {
/* Our pipeline request limit is the same that our keepalive limit */
+ if (cs->parser.i < 0 ||
+ (unsigned int) (cs->parser.i + 1) >= cs->body_length) {
+ goto shutdown;
+ }
+
cs->counter_connections++;
len = (cs->body_length - cs->parser.i) -1;
+ if (len <= 0) {
+ goto shutdown;
+ }
memmove(cs->body,
cs->body + cs->parser.i + 1,
len);
cs->body_length = len;
/* Prepare for next one */
- sr = mk_list_entry_first(&cs->request_list, struct mk_http_request, _head);
+ if (mk_list_is_empty(&cs->request_list) == 0) {
+ cs->close_now = MK_TRUE;
+ goto shutdown;
+ }
+ sr = &cs->sr_fixed;
mk_http_request_free(sr, server);
mk_http_request_init(cs, sr, server);
mk_http_parser_init(&cs->parser);
@@ -1621,9 +1658,10 @@ int mk_http_sched_done(struct mk_sched_conn *conn,
struct mk_http_request *sr;
session = mk_http_session_get(conn);
- sr = mk_list_entry_first(&session->request_list,
- struct mk_http_request, _head);
- mk_plugin_stage_run_40(session, sr, server);
+ if (mk_list_is_empty(&session->request_list) != 0) {
+ sr = &session->sr_fixed;
+ mk_plugin_stage_run_40(session, sr, server);
+ }
return mk_http_request_end(session, server);
}
--
2.45.4
From fcbb70eec4c9fa9201b3b71044e794d3bd11f82f Mon Sep 17 00:00:00 2001
From: Eduardo Silva <eduardo@chronosphere.io>
Date: Thu, 9 Apr 2026 12:11:57 -0600
Subject: [PATCH 2/3] server: parser: harden boundary checks
Tighten parser and helper validation around explicit lengths and
buffer boundaries.
Require exact header literal matches, validate chunk length tokens,
and guard helper routines that previously trusted inconsistent
pointer or length state.
Verified by rebuilding with cmake --build build and replaying the
reported malformed request fixtures against build/bin/monkey.
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
---
lib/monkey/include/monkey/mk_http_parser.h | 6 +++++-
lib/monkey/mk_server/mk_http_parser.c | 13 +++++++++++++
lib/monkey/mk_server/mk_mimetype.c | 7 ++++++-
lib/monkey/mk_server/mk_user.c | 2 +-
4 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/lib/monkey/include/monkey/mk_http_parser.h b/lib/monkey/include/monkey/mk_http_parser.h
index 6d45c39..5ae5c60 100644
--- a/lib/monkey/include/monkey/mk_http_parser.h
+++ b/lib/monkey/include/monkey/mk_http_parser.h
@@ -335,7 +335,11 @@ static inline void mk_http_parser_init(struct mk_http_parser *p)
static inline int mk_http_parser_more(struct mk_http_parser *p, int len)
{
- if (abs(len - p->i) - 1 > 0) {
+ if (len <= 0 || p->i < 0) {
+ return MK_FALSE;
+ }
+
+ if ((p->i + 1) < len) {
return MK_TRUE;
}
diff --git a/lib/monkey/mk_server/mk_http_parser.c b/lib/monkey/mk_server/mk_http_parser.c
index 4e7aa31..8fc4da1 100644
--- a/lib/monkey/mk_server/mk_http_parser.c
+++ b/lib/monkey/mk_server/mk_http_parser.c
@@ -172,6 +172,16 @@ static inline void request_set(mk_ptr_t *ptr, struct mk_http_parser *p, char *bu
static inline int header_cmp(const char *expected, char *value, int len)
{
int i = 0;
+ size_t expected_len;
+
+ if (len < 0) {
+ return -1;
+ }
+
+ expected_len = strlen(expected);
+ if ((size_t) len != expected_len) {
+ return -1;
+ }
if (len >= 8) {
if (expected[0] != tolower(value[0])) return -1;
@@ -503,6 +513,9 @@ int mk_http_parser(struct mk_http_request *req, struct mk_http_parser *p,
if (p->start + 6 >= p->i) {
continue;
}
+ if (ptr == tmp || *ptr != '\0') {
+ return MK_HTTP_PARSER_ERROR;
+ }
tmp = p->start;
if (buffer[tmp] == 'H' &&
diff --git a/lib/monkey/mk_server/mk_mimetype.c b/lib/monkey/mk_server/mk_mimetype.c
index b86b4ef..5462ea5 100644
--- a/lib/monkey/mk_server/mk_mimetype.c
+++ b/lib/monkey/mk_server/mk_mimetype.c
@@ -197,7 +197,12 @@ struct mk_mimetype *mk_mimetype_find(struct mk_server *server, mk_ptr_t *filenam
{
int j, len;
- j = len = filename->len;
+ if (!filename->data || filename->len <= 0) {
+ return NULL;
+ }
+
+ len = filename->len;
+ j = len - 1;
/* looking for extension */
while (j >= 0 && filename->data[j] != '.') {
diff --git a/lib/monkey/mk_server/mk_user.c b/lib/monkey/mk_server/mk_user.c
index 7200ff0..716331a 100644
--- a/lib/monkey/mk_server/mk_user.c
+++ b/lib/monkey/mk_server/mk_user.c
@@ -46,7 +46,7 @@ int mk_user_init(struct mk_http_session *cs, struct mk_http_request *sr,
}
limit = mk_string_char_search(sr->uri_processed.data + offset, '/',
- sr->uri_processed.len);
+ sr->uri_processed.len - offset);
if (limit == -1) {
limit = (sr->uri_processed.len) - offset;
--
2.45.4
From d9be8a3839d0e024cb219702076357f9f054b3d3 Mon Sep 17 00:00:00 2001
From: Eduardo Silva <eduardo@chronosphere.io>
Date: Thu, 9 Apr 2026 12:43:31 -0600
Subject: [PATCH 3/3] server: scheduler: guard protocol close callback
Avoid calling a null cb_close handler from the scheduler close
and timeout paths.
This fixes the HTTP/2 upgrade case where the protocol handler can be
switched to mk_http2_handler even though that handler does not
implement cb_close.
Verified by rebuilding with cmake --build build.
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/monkey/monkey/pull/434.patch
---
lib/monkey/mk_server/mk_scheduler.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/monkey/mk_server/mk_scheduler.c b/lib/monkey/mk_server/mk_scheduler.c
index a680d3c..3cf0ba4 100644
--- a/lib/monkey/mk_server/mk_scheduler.c
+++ b/lib/monkey/mk_server/mk_scheduler.c
@@ -598,8 +598,10 @@ int mk_sched_check_timeouts(struct mk_sched_worker *sched,
MK_TRACE("Scheduler, closing fd %i due TIMEOUT",
conn->event.fd);
MK_LT_SCHED(conn->event.fd, "TIMEOUT_CONN_PENDING");
- conn->protocol->cb_close(conn, sched, MK_SCHED_CONN_TIMEOUT,
- server);
+ if (conn->protocol->cb_close) {
+ conn->protocol->cb_close(conn, sched, MK_SCHED_CONN_TIMEOUT,
+ server);
+ }
mk_sched_drop_connection(conn, sched, server);
}
}
@@ -749,7 +751,7 @@ int mk_sched_event_close(struct mk_sched_conn *conn,
MK_TRACE("[FD %i] Connection Handler, closed", conn->event.fd);
mk_event_del(sched->loop, &conn->event);
- if (type != MK_EP_SOCKET_DONE) {
+ if (type != MK_EP_SOCKET_DONE && conn->protocol->cb_close) {
conn->protocol->cb_close(conn, sched, type, server);
}
/*
--
2.45.4