summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnkur Tyagi <ankur.tyagi85@gmail.com>2026-01-01 10:16:27 +0100
committerGyorgy Sarvari <skandigraun@gmail.com>2026-01-08 22:03:02 +0100
commit71adc2f371177c9de19d35fbd6c2472bc11f49bf (patch)
treea1f76cf09433676b86045aefacc31847a488f021
parent15750d55842605b98fc3ac1ea8e03e7471a6500f (diff)
downloadmeta-openembedded-71adc2f371177c9de19d35fbd6c2472bc11f49bf.tar.gz
civetweb: patch CVE-2025-9648
Details https://nvd.nist.gov/vuln/detail/CVE-2025-9648 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com> (cherry picked from commit eb338ebb606f22363be5b4114e25a10b494b4f55) Rebased patch on Kirkstone's civetweb. Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
-rw-r--r--meta-networking/recipes-connectivity/civetweb/civetweb/CVE-2025-9648.patch234
-rw-r--r--meta-networking/recipes-connectivity/civetweb/civetweb_git.bb1
2 files changed, 235 insertions, 0 deletions
diff --git a/meta-networking/recipes-connectivity/civetweb/civetweb/CVE-2025-9648.patch b/meta-networking/recipes-connectivity/civetweb/civetweb/CVE-2025-9648.patch
new file mode 100644
index 0000000000..e8ee00541e
--- /dev/null
+++ b/meta-networking/recipes-connectivity/civetweb/civetweb/CVE-2025-9648.patch
@@ -0,0 +1,234 @@
1From 6f10111d24f9f7bdb637bba77c27700ecff56244 Mon Sep 17 00:00:00 2001
2From: bel2125 <bel2125@gmail.com>
3Date: Tue, 2 Sep 2025 14:08:41 +0200
4Subject: [PATCH] Make parsing of URL encoded forms more robust
5
6Reject requests that obviously violate the URL encoding.
7Fixes #1348
8
9CVE: CVE-2025-9648
10Upstream-Status: Backport [https://github.com/civetweb/civetweb/commit/782e18903515f43bafbf2e668994e82bdfa51133]
11(cherry picked from commit 782e18903515f43bafbf2e668994e82bdfa51133)
12Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
13---
14 src/civetweb.c | 7 ++++++-
15 src/handle_form.inl | 46 +++++++++++++++++++++++++++++++++++++--------
16 2 files changed, 44 insertions(+), 9 deletions(-)
17
18diff --git a/src/civetweb.c b/src/civetweb.c
19index 5452b36d..f843300c 100644
20--- a/src/civetweb.c
21+++ b/src/civetweb.c
22@@ -7143,11 +7143,15 @@ mg_url_decode(const char *src,
23 i += 2;
24 } else if (is_form_url_encoded && (src[i] == '+')) {
25 dst[j] = ' ';
26+ } else if ((unsigned char)src[i] <= ' ') {
27+ return -1; /* invalid character */
28 } else {
29 dst[j] = src[i];
30 }
31 }
32
33+#undef HEXTOI
34+
35 dst[j] = '\0'; /* Null-terminate the destination */
36
37 return (i >= src_len) ? j : -1;
38diff --git a/src/handle_form.inl b/src/handle_form.inl
39index be477a05..0ebaf560 100644
40--- a/src/handle_form.inl
41+++ b/src/handle_form.inl
42@@ -39,7 +39,7 @@ url_encoded_field_found(const struct mg_connection *conn,
43 mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
44
45 if (((size_t)key_dec_len >= (size_t)sizeof(key_dec)) || (key_dec_len < 0)) {
46- return MG_FORM_FIELD_STORAGE_SKIP;
47+ return MG_FORM_FIELD_STORAGE_ABORT;
48 }
49
50 if (filename) {
51@@ -53,7 +53,7 @@ url_encoded_field_found(const struct mg_connection *conn,
52 || (filename_dec_len < 0)) {
53 /* Log error message and skip this field. */
54 mg_cry_internal(conn, "%s: Cannot decode filename", __func__);
55- return MG_FORM_FIELD_STORAGE_SKIP;
56+ return MG_FORM_FIELD_STORAGE_ABORT;
57 }
58 remove_dot_segments(filename_dec);
59
60@@ -93,6 +93,7 @@ url_encoded_field_get(
61 struct mg_form_data_handler *fdh)
62 {
63 char key_dec[1024];
64+ int key_dec_len;
65
66 char *value_dec = (char *)mg_malloc_ctx(value_len + 1, conn->phys_ctx);
67 int value_dec_len, ret;
68@@ -106,7 +107,8 @@ url_encoded_field_get(
69 return MG_FORM_FIELD_STORAGE_ABORT;
70 }
71
72- mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
73+ key_dec_len = mg_url_decode(
74+ key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
75
76 value_dec_len =
77 mg_url_decode(value, (int)value_len, value_dec, (int)value_len + 1, 1);
78@@ -111,6 +113,11 @@ url_encoded_field_get(
79 value_dec_len =
80 mg_url_decode(value, (int)value_len, value_dec, (int)value_len + 1, 1);
81
82+ if ((key_dec_len < 0) || (value_dec_len < 0)) {
83+ mg_free(value_dec);
84+ return MG_FORM_FIELD_STORAGE_ABORT;
85+ }
86+
87 ret = fdh->field_get(key_dec,
88 value_dec,
89 (size_t)value_dec_len,
90@@ -130,9 +137,13 @@ unencoded_field_get(const struct mg_connection *conn,
91 struct mg_form_data_handler *fdh)
92 {
93 char key_dec[1024];
94+ int key_dec_len;
95 (void)conn;
96
97- mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
98+ key_dec_len = mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1);
99+ if (key_dec_len < 0) {
100+ return MG_FORM_FIELD_STORAGE_ABORT;
101+ }
102
103 return fdh->field_get(key_dec, value, value_len, fdh->user_data);
104 }
105@@ -182,6 +193,7 @@ mg_handle_form_request(struct mg_connection *conn,
106 int buf_fill = 0;
107 int r;
108 int field_count = 0;
109+ int abort_read = 0;
110 struct mg_file fstore = STRUCT_FILE_INITIALIZER;
111 int64_t file_size = 0; /* init here, to a avoid a false positive
112 "uninitialized variable used" warning */
113@@ -274,6 +286,7 @@ mg_handle_form_request(struct mg_connection *conn,
114 conn, data, (size_t)keylen, val, (size_t)vallen, fdh);
115 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
116 /* Stop request handling */
117+ abort_read = 1;
118 break;
119 }
120 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
121@@ -308,6 +321,7 @@ mg_handle_form_request(struct mg_connection *conn,
122 r = field_stored(conn, path, file_size, fdh);
123 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
124 /* Stop request handling */
125+ abort_read = 1;
126 break;
127 }
128
129@@ -346,6 +360,7 @@ mg_handle_form_request(struct mg_connection *conn,
130 if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
131 == MG_FORM_FIELD_STORAGE_ABORT) {
132 /* Stop parsing the request */
133+ abort_read = 1;
134 break;
135 }
136
137@@ -374,7 +389,7 @@ mg_handle_form_request(struct mg_connection *conn,
138 * Here we use "POST", and read the data from the request body.
139 * The data read on the fly, so it is not required to buffer the
140 * entire request in memory before processing it. */
141- for (;;) {
142+ while (!abort_read) {
143 const char *val;
144 const char *next;
145 ptrdiff_t keylen, vallen;
146@@ -428,6 +443,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@@ -458,6 +474,15 @@ mg_handle_form_request(struct mg_connection *conn,
155 vallen = (ptrdiff_t)strlen(val);
156 next = val + vallen;
157 end_of_key_value_pair_found = all_data_read;
158+ if ((buf + buf_fill) > (val + vallen)) {
159+ /* Avoid DoS attacks by having a zero byte in the middle of
160+ * a request that is supposed to be URL encoded. Since this
161+ * request is certainly invalid, according to the protocol
162+ * specification, stop processing it. Fixes #1348 */
163+ abort_read = 1;
164+ break;
165+ }
166+
167 }
168
169 if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
170@@ -479,6 +504,7 @@ mg_handle_form_request(struct mg_connection *conn,
171 get_block++;
172 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
173 /* Stop request handling */
174+ abort_read = 1;
175 break;
176 }
177 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
178@@ -539,7 +565,6 @@ mg_handle_form_request(struct mg_connection *conn,
179 val = buf;
180 }
181 }
182-
183 } while (!end_of_key_value_pair_found);
184
185 #if !defined(NO_FILESYSTEMS)
186@@ -550,6 +575,7 @@ mg_handle_form_request(struct mg_connection *conn,
187 r = field_stored(conn, path, file_size, fdh);
188 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
189 /* Stop request handling */
190+ abort_read = 1;
191 break;
192 }
193 } else {
194@@ -563,7 +589,7 @@ mg_handle_form_request(struct mg_connection *conn,
195 }
196 #endif /* NO_FILESYSTEMS */
197
198- if (all_data_read && (buf_fill == 0)) {
199+ if ((all_data_read && (buf_fill == 0)) || abort_read) {
200 /* nothing more to process */
201 break;
202 }
203@@ -919,6 +945,7 @@ mg_handle_form_request(struct mg_connection *conn,
204 get_block++;
205 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
206 /* Stop request handling */
207+ abort_read = 1;
208 break;
209 }
210 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
211@@ -995,6 +1022,7 @@ mg_handle_form_request(struct mg_connection *conn,
212 fdh);
213 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
214 /* Stop request handling */
215+ abort_read = 1;
216 break;
217 }
218 if (r == MG_FORM_FIELD_HANDLE_NEXT) {
219@@ -1023,6 +1051,7 @@ mg_handle_form_request(struct mg_connection *conn,
220 r = field_stored(conn, path, file_size, fdh);
221 if (r == MG_FORM_FIELD_HANDLE_ABORT) {
222 /* Stop request handling */
223+ abort_read = 1;
224 break;
225 }
226 } else {
227@@ -1041,6 +1070,7 @@ mg_handle_form_request(struct mg_connection *conn,
228 if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT)
229 == MG_FORM_FIELD_STORAGE_ABORT) {
230 /* Stop parsing the request */
231+ abort_read = 1;
232 break;
233 }
234
diff --git a/meta-networking/recipes-connectivity/civetweb/civetweb_git.bb b/meta-networking/recipes-connectivity/civetweb/civetweb_git.bb
index 1648d13d99..ed80eac08e 100644
--- a/meta-networking/recipes-connectivity/civetweb/civetweb_git.bb
+++ b/meta-networking/recipes-connectivity/civetweb/civetweb_git.bb
@@ -10,6 +10,7 @@ SRC_URI = "git://github.com/civetweb/civetweb.git;branch=master;protocol=https \
10 file://0001-Unittest-Link-librt-and-libm-using-l-option.patch \ 10 file://0001-Unittest-Link-librt-and-libm-using-l-option.patch \
11 file://0001-Sanitize-upload-filename-like-URL.patch \ 11 file://0001-Sanitize-upload-filename-like-URL.patch \
12 file://0002-handle_form-example-Upload-to-temporary-directory-an.patch \ 12 file://0002-handle_form-example-Upload-to-temporary-directory-an.patch \
13 file://CVE-2025-9648.patch \
13 " 14 "
14 15
15S = "${WORKDIR}/git" 16S = "${WORKDIR}/git"