Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 314 additions & 0 deletions SPECS/fluent-bit/CVE-2025-63657.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
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

8 changes: 6 additions & 2 deletions SPECS/fluent-bit/fluent-bit.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: Fast and Lightweight Log processor and forwarder for Linux, BSD and OSX
Name: fluent-bit
Version: 3.1.10
Release: 4%{?dist}
Release: 5%{?dist}
License: Apache-2.0
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -19,6 +19,7 @@ Patch8: CVE-2025-12970.patch
Patch9: CVE-2025-12977.patch
Patch10: CVE-2025-12969.patch
Patch11: CVE-2025-62408.patch
Patch12: CVE-2025-63657.patch
BuildRequires: bison
BuildRequires: cmake
BuildRequires: cyrus-sasl-devel
Expand Down Expand Up @@ -93,6 +94,9 @@ Development files for %{name}
%{_libdir}/fluent-bit/*.so

%changelog
* Mon Apr 13 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.1.10-5
- Patch for CVE-2025-63657

* Wed Dec 17 2025 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.1.10-4
- Patch for CVE-2025-62408

Expand Down Expand Up @@ -120,7 +124,7 @@ Development files for %{name}
* Tue Dec 10 2024 Sudipta Pandit <sudpandit@microsoft.com> - 3.1.9-2
- Backport fixes for CVE-2024-27532

* Tue Nov 23 2024 Paul Meyer <paul.meyer@microsoft.com> - 3.1.9-1
* Sat Nov 23 2024 Paul Meyer <paul.meyer@microsoft.com> - 3.1.9-1
- Update to 3.1.9 to enable Lua filter plugin using system luajit library.
- Remove patches for CVE-2024-25629 and CVE-2024-28182 as they are fixed in 3.1.9.
- [Jon Slobodzian] Reconciled with Fasttrack/3.0 on 11/23, updated Changelog date from 11/5.
Expand Down
Loading