Skip to content

Commit 792cfc1

Browse files
[AutoPR- Security] Patch ceph for CVE-2025-9648 [HIGH] (microsoft#14779)
Co-authored-by: BinduSri-6522866 <[email protected]>
1 parent 66c7638 commit 792cfc1

File tree

2 files changed

+259
-1
lines changed

2 files changed

+259
-1
lines changed

SPECS/ceph/CVE-2025-9648.patch

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
From 726ee3dcb67c81c57dae77866135159c3c17181e Mon Sep 17 00:00:00 2001
2+
From: AllSpark <[email protected]>
3+
Date: Fri, 3 Oct 2025 06:18:32 +0000
4+
Subject: [PATCH] Backport: Make parsing of URL encoded forms more robust;
5+
reject invalid characters, abort when decoding fails; add abort_read
6+
handling; update copyrights. Fixes #1348
7+
8+
Signed-off-by: Azure Linux Security Servicing Account <[email protected]>
9+
Upstream-reference: AI Backport of https://github.com/civetweb/civetweb/commit/782e18903515f43bafbf2e668994e82bdfa51133.patch
10+
---
11+
.../3rdparty/civetweb/src/civetweb.c | 7 ++-
12+
.../3rdparty/civetweb/src/handle_form.inl | 46 +++++++++++++++----
13+
2 files changed, 44 insertions(+), 9 deletions(-)
14+
15+
diff --git a/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/civetweb.c b/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/civetweb.c
16+
index fea9e6f98..4459aa065 100644
17+
--- a/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/civetweb.c
18+
+++ b/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/civetweb.c
19+
@@ -1,4 +1,4 @@
20+
-/* Copyright (c) 2013-2021 the Civetweb developers
21+
+/* Copyright (c) 2013-2025 the Civetweb developers
22+
* Copyright (c) 2004-2013 Sergey Lyubka
23+
*
24+
* Permission is hereby granted, free of charge, to any person obtaining a copy
25+
@@ -6953,6 +6953,7 @@ mg_url_decode(const char *src,
26+
int is_form_url_encoded)
27+
{
28+
int i, j, a, b;
29+
+
30+
#define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W'))
31+
32+
for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
33+
@@ -6965,11 +6966,15 @@ mg_url_decode(const char *src,
34+
i += 2;
35+
} else if (is_form_url_encoded && (src[i] == '+')) {
36+
dst[j] = ' ';
37+
+ } else if ((unsigned char)src[i] <= ' ') {
38+
+ return -1; /* invalid character */
39+
} else {
40+
dst[j] = src[i];
41+
}
42+
}
43+
44+
+#undef HEXTOI
45+
+
46+
dst[j] = '\0'; /* Null-terminate the destination */
47+
48+
return (i >= src_len) ? j : -1;
49+
diff --git a/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/handle_form.inl b/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/handle_form.inl
50+
index eaad88d78..089b66c4c 100644
51+
--- a/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/handle_form.inl
52+
+++ b/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/handle_form.inl
53+
@@ -1,4 +1,4 @@
54+
-/* Copyright (c) 2016-2021 the Civetweb developers
55+
+/* Copyright (c) 2016-2025 the Civetweb developers
56+
*
57+
* Permission is hereby granted, free of charge, to any person obtaining a copy
58+
* of this software and associated documentation files (the "Software"), to deal
59+
@@ -39,7 +39,7 @@ url_encoded_field_found(const struct mg_connection *conn,
60+
mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
61+
62+
if (((size_t)key_dec_len >= (size_t)sizeof(key_dec)) || (key_dec_len < 0)) {
63+
- return MG_FORM_FIELD_STORAGE_SKIP;
64+
+ return MG_FORM_FIELD_STORAGE_ABORT;
65+
}
66+
67+
if (filename) {
68+
@@ -53,7 +53,7 @@ url_encoded_field_found(const struct mg_connection *conn,
69+
|| (filename_dec_len < 0)) {
70+
/* Log error message and skip this field. */
71+
mg_cry_internal(conn, "%s: Cannot decode filename", __func__);
72+
- return MG_FORM_FIELD_STORAGE_SKIP;
73+
+ return MG_FORM_FIELD_STORAGE_ABORT;
74+
}
75+
remove_dot_segments(filename_dec);
76+
77+
@@ -95,6 +95,7 @@ url_encoded_field_get(
78+
struct mg_form_data_handler *fdh)
79+
{
80+
char key_dec[1024];
81+
+ int key_dec_len;
82+
83+
char *value_dec = (char *)mg_malloc_ctx(*value_len + 1, conn->phys_ctx);
84+
int value_dec_len, ret;
85+
@@ -108,7 +109,8 @@ url_encoded_field_get(
86+
return MG_FORM_FIELD_STORAGE_ABORT;
87+
}
88+
89+
- mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
90+
+ key_dec_len = mg_url_decode(
91+
+ key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
92+
93+
if (*value_len >= 2 && value[*value_len - 2] == '%')
94+
*value_len -= 2;
95+
@@ -117,6 +119,11 @@ url_encoded_field_get(
96+
value_dec_len = mg_url_decode(
97+
value, (int)*value_len, value_dec, ((int)*value_len) + 1, 1);
98+
99+
+ if ((key_dec_len < 0) || (value_dec_len < 0)) {
100+
+ mg_free(value_dec);
101+
+ return MG_FORM_FIELD_STORAGE_ABORT;
102+
+ }
103+
+
104+
ret = fdh->field_get(key_dec,
105+
value_dec,
106+
(size_t)value_dec_len,
107+
@@ -136,9 +143,13 @@ unencoded_field_get(const struct mg_connection *conn,
108+
struct mg_form_data_handler *fdh)
109+
{
110+
char key_dec[1024];
111+
+ int key_dec_len;
112+
(void)conn;
113+
114+
- mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
115+
+ key_dec_len = mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
116+
+ if (key_dec_len < 0) {
117+
+ return MG_FORM_FIELD_STORAGE_ABORT;
118+
+ }
119+
120+
return fdh->field_get(key_dec, value, value_len, fdh->user_data);
121+
}
122+
@@ -188,6 +199,7 @@ mg_handle_form_request(struct mg_connection *conn,
123+
int buf_fill = 0;
124+
int r;
125+
int field_count = 0;
126+
+ int abort_read = 0;
127+
struct mg_file fstore = STRUCT_FILE_INITIALIZER;
128+
int64_t file_size = 0; /* init here, to a avoid a false positive
129+
"uninitialized variable used" warning */
130+
@@ -278,6 +290,7 @@ mg_handle_form_request(struct mg_connection *conn,
131+
conn, data, (size_t)keylen, val, (size_t *)&vallen, fdh);
132+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
133+
/* Stop request handling */
134+
+ abort_read = 1;
135+
break;
136+
}
137+
if (r == MG_FORM_FIELD_HANDLE_NEXT) {
138+
@@ -320,6 +333,7 @@ mg_handle_form_request(struct mg_connection *conn,
139+
r = field_stored(conn, path, file_size, fdh);
140+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
141+
/* Stop request handling */
142+
+ abort_read = 1;
143+
break;
144+
}
145+
146+
@@ -358,6 +372,7 @@ mg_handle_form_request(struct mg_connection *conn,
147+
if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
148+
== MG_FORM_FIELD_STORAGE_ABORT) {
149+
/* Stop parsing the request */
150+
+ abort_read = 1;
151+
break;
152+
}
153+
154+
@@ -386,7 +401,7 @@ mg_handle_form_request(struct mg_connection *conn,
155+
* Here we use "POST", and read the data from the request body.
156+
* The data read on the fly, so it is not required to buffer the
157+
* entire request in memory before processing it. */
158+
- for (;;) {
159+
+ while (!abort_read) {
160+
const char *val;
161+
const char *next;
162+
ptrdiff_t keylen, vallen;
163+
@@ -440,6 +455,7 @@ mg_handle_form_request(struct mg_connection *conn,
164+
if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
165+
== MG_FORM_FIELD_STORAGE_ABORT) {
166+
/* Stop parsing the request */
167+
+ abort_read = 1;
168+
break;
169+
}
170+
171+
@@ -468,6 +484,15 @@ mg_handle_form_request(struct mg_connection *conn,
172+
} else {
173+
vallen = (ptrdiff_t)strlen(val);
174+
end_of_key_value_pair_found = all_data_read;
175+
+ if ((buf + buf_fill) > (val + vallen)) {
176+
+ /* Avoid DoS attacks by having a zero byte in the middle of
177+
+ * a request that is supposed to be URL encoded. Since this
178+
+ * request is certainly invalid, according to the protocol
179+
+ * specification, stop processing it. Fixes #1348 */
180+
+ abort_read = 1;
181+
+ break;
182+
+ }
183+
+
184+
}
185+
186+
if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
187+
@@ -489,6 +514,7 @@ mg_handle_form_request(struct mg_connection *conn,
188+
get_block++;
189+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
190+
/* Stop request handling */
191+
+ abort_read = 1;
192+
break;
193+
}
194+
if (r == MG_FORM_FIELD_HANDLE_NEXT) {
195+
@@ -557,7 +583,6 @@ mg_handle_form_request(struct mg_connection *conn,
196+
val = buf;
197+
}
198+
}
199+
-
200+
} while (!end_of_key_value_pair_found);
201+
202+
#if !defined(NO_FILESYSTEMS)
203+
@@ -568,6 +593,7 @@ mg_handle_form_request(struct mg_connection *conn,
204+
r = field_stored(conn, path, file_size, fdh);
205+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
206+
/* Stop request handling */
207+
+ abort_read = 1;
208+
break;
209+
}
210+
} else {
211+
@@ -581,7 +607,7 @@ mg_handle_form_request(struct mg_connection *conn,
212+
}
213+
#endif /* NO_FILESYSTEMS */
214+
215+
- if (all_data_read && (buf_fill == 0)) {
216+
+ if ((all_data_read && (buf_fill == 0)) || abort_read) {
217+
/* nothing more to process */
218+
break;
219+
}
220+
@@ -937,6 +963,7 @@ mg_handle_form_request(struct mg_connection *conn,
221+
get_block++;
222+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
223+
/* Stop request handling */
224+
+ abort_read = 1;
225+
break;
226+
}
227+
if (r == MG_FORM_FIELD_HANDLE_NEXT) {
228+
@@ -1011,6 +1038,7 @@ mg_handle_form_request(struct mg_connection *conn,
229+
fdh);
230+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
231+
/* Stop request handling */
232+
+ abort_read = 1;
233+
break;
234+
}
235+
if (r == MG_FORM_FIELD_HANDLE_NEXT) {
236+
@@ -1039,6 +1067,7 @@ mg_handle_form_request(struct mg_connection *conn,
237+
r = field_stored(conn, path, file_size, fdh);
238+
if (r == MG_FORM_FIELD_HANDLE_ABORT) {
239+
/* Stop request handling */
240+
+ abort_read = 1;
241+
break;
242+
}
243+
} else {
244+
@@ -1057,6 +1086,7 @@ mg_handle_form_request(struct mg_connection *conn,
245+
if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
246+
== MG_FORM_FIELD_STORAGE_ABORT) {
247+
/* Stop parsing the request */
248+
+ abort_read = 1;
249+
break;
250+
}
251+
252+
--
253+
2.45.4
254+

SPECS/ceph/ceph.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Summary: User space components of the Ceph file system
66
Name: ceph
77
Version: 18.2.2
8-
Release: 10%{?dist}
8+
Release: 11%{?dist}
99
License: LGPLv2 and LGPLv3 and CC-BY-SA and GPLv2 and Boost and BSD and MIT and Public Domain and GPLv3 and ASL-2.0
1010
URL: https://ceph.io/
1111
Vendor: Microsoft Corporation
@@ -30,6 +30,7 @@ Patch15: CVE-2021-28361.patch
3030
Patch16: CVE-2020-14378.patch
3131
Patch17: CVE-2025-52555.patch
3232
Patch18: CVE-2024-48916.patch
33+
Patch19: CVE-2025-9648.patch
3334
#
3435
# Copyright (C) 2004-2019 The Ceph Project Developers. See COPYING file
3536
# at the top-level directory of this distribution and at
@@ -2020,6 +2021,9 @@ exit 0
20202021
%config %{_sysconfdir}/prometheus/ceph/ceph_default_alerts.yml
20212022

20222023
%changelog
2024+
* Fri Oct 03 2025 Azure Linux Security Servicing Account <[email protected]> - 18.2.2-11
2025+
- Patch for CVE-2025-9648
2026+
20232027
* Fri Aug 01 2025 Azure Linux Security Servicing Account <[email protected]> - 18.2.2-10
20242028
- Patch for CVE-2024-48916
20252029

0 commit comments

Comments
 (0)