summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHitendra Prajapati <hprajapati@mvista.com>2023-03-31 10:17:32 +0530
committerArmin Kuster <akuster808@gmail.com>2023-04-06 07:32:11 -0400
commit94b30b7d85c5fb862b36dd66e8dca09cd940f13b (patch)
tree2bd689b953e396c4e2ecf54d76b06ced19812b9c
parentf1d4acc09de9bd8e5e18f45f1e7efadece527195 (diff)
downloadmeta-openembedded-94b30b7d85c5fb862b36dd66e8dca09cd940f13b.tar.gz
syslog-ng: CVE-2022-38725 An integer overflow in the RFC3164 parser
Upstream-Status: Backport from https://github.com/syslog-ng/syslog-ng/commit/b5a060f2ebb8d794f508436a12e4d4163f94b1b8 && https://github.com/syslog-ng/syslog-ng/commit/81a07263f1e522a376d3a30f96f51df3f2879f8a && https://github.com/syslog-ng/syslog-ng/commit/4b8dc56ca8eaeac4c8751a305eb7eeefab8dc89d && https://github.com/syslog-ng/syslog-ng/commit/73b5c300b8fde5e7a4824baa83a04931279abb37 && https://github.com/syslog-ng/syslog-ng/commit/45f051239312e43bd4f92b9339fe67c6798a0321 && https://github.com/syslog-ng/syslog-ng/commit/09f489c89c826293ff8cbd282cfc866ab56054c4 && https://github.com/syslog-ng/syslog-ng/commit/8c6e2c1c41b0fcc5fbd464c35f4dac7102235396 && https://github.com/syslog-ng/syslog-ng/commit/56f881c5eaa3d8c02c96607c4b9e4eaf959a044d Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta-oe/recipes-support/syslog-ng/files/CVE-2022-38725.patch629
-rw-r--r--meta-oe/recipes-support/syslog-ng/syslog-ng_3.24.1.bb1
2 files changed, 630 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/syslog-ng/files/CVE-2022-38725.patch b/meta-oe/recipes-support/syslog-ng/files/CVE-2022-38725.patch
new file mode 100644
index 0000000000..4a09c8c7fa
--- /dev/null
+++ b/meta-oe/recipes-support/syslog-ng/files/CVE-2022-38725.patch
@@ -0,0 +1,629 @@
1From 73b5c300b8fde5e7a4824baa83a04931279abb37 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?=
3 <laszlo.varady@protonmail.com>
4Date: Sat, 20 Aug 2022 12:42:38 +0200
5Subject: [PATCH] CVE-2022-38725
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Signed-off-by: László Várady <laszlo.varady@protonmail.com>
11Signed-off-by: Balazs Scheidler <bazsi77@gmail.com>
12
13Upstream-Status: Backport from [https://github.com/syslog-ng/syslog-ng/commit/b5a060f2ebb8d794f508436a12e4d4163f94b1b8 && https://github.com/syslog-ng/syslog-ng/commit/81a07263f1e522a376d3a30f96f51df3f2879f8a && https://github.com/syslog-ng/syslog-ng/commit/4b8dc56ca8eaeac4c8751a305eb7eeefab8dc89d && https://github.com/syslog-ng/syslog-ng/commit/73b5c300b8fde5e7a4824baa83a04931279abb37 && https://github.com/syslog-ng/syslog-ng/commit/45f051239312e43bd4f92b9339fe67c6798a0321 && https://github.com/syslog-ng/syslog-ng/commit/09f489c89c826293ff8cbd282cfc866ab56054c4 && https://github.com/syslog-ng/syslog-ng/commit/8c6e2c1c41b0fcc5fbd464c35f4dac7102235396 && https://github.com/syslog-ng/syslog-ng/commit/56f881c5eaa3d8c02c96607c4b9e4eaf959a044d]
14CVE: CVE-2022-38725
15Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
16---
17 lib/timeutils/scan-timestamp.c | 68 +++++----
18 lib/timeutils/tests/test_scan-timestamp.c | 133 ++++++++++++++++--
19 modules/syslogformat/CMakeLists.txt | 2 +
20 modules/syslogformat/Makefile.am | 2 +
21 modules/syslogformat/syslog-format.c | 12 +-
22 modules/syslogformat/tests/CMakeLists.txt | 1 +
23 modules/syslogformat/tests/Makefile.am | 9 ++
24 .../syslogformat/tests/test_syslog_format.c | 104 ++++++++++++++
25 8 files changed, 284 insertions(+), 47 deletions(-)
26 create mode 100644 modules/syslogformat/tests/CMakeLists.txt
27 create mode 100644 modules/syslogformat/tests/Makefile.am
28 create mode 100644 modules/syslogformat/tests/test_syslog_format.c
29
30diff --git a/lib/timeutils/scan-timestamp.c b/lib/timeutils/scan-timestamp.c
31index 41ead1a..ec9746b 100644
32--- a/lib/timeutils/scan-timestamp.c
33+++ b/lib/timeutils/scan-timestamp.c
34@@ -34,41 +34,43 @@ scan_day_abbrev(const gchar **buf, gint *left, gint *wday)
35 {
36 *wday = -1;
37
38- if (*left < 3)
39+ const gsize abbrev_length = 3;
40+
41+ if (*left < abbrev_length)
42 return FALSE;
43
44 switch (**buf)
45 {
46 case 'S':
47- if (strncasecmp(*buf, "Sun", 3) == 0)
48+ if (strncasecmp(*buf, "Sun", abbrev_length) == 0)
49 *wday = 0;
50- else if (strncasecmp(*buf, "Sat", 3) == 0)
51+ else if (strncasecmp(*buf, "Sat", abbrev_length) == 0)
52 *wday = 6;
53 break;
54 case 'M':
55- if (strncasecmp(*buf, "Mon", 3) == 0)
56+ if (strncasecmp(*buf, "Mon", abbrev_length) == 0)
57 *wday = 1;
58 break;
59 case 'T':
60- if (strncasecmp(*buf, "Tue", 3) == 0)
61+ if (strncasecmp(*buf, "Tue", abbrev_length) == 0)
62 *wday = 2;
63- else if (strncasecmp(*buf, "Thu", 3) == 0)
64+ else if (strncasecmp(*buf, "Thu", abbrev_length) == 0)
65 *wday = 4;
66 break;
67 case 'W':
68- if (strncasecmp(*buf, "Wed", 3) == 0)
69+ if (strncasecmp(*buf, "Wed", abbrev_length) == 0)
70 *wday = 3;
71 break;
72 case 'F':
73- if (strncasecmp(*buf, "Fri", 3) == 0)
74+ if (strncasecmp(*buf, "Fri", abbrev_length) == 0)
75 *wday = 5;
76 break;
77 default:
78 return FALSE;
79 }
80
81- (*buf) += 3;
82- (*left) -= 3;
83+ (*buf) += abbrev_length;
84+ (*left) -= abbrev_length;
85 return TRUE;
86 }
87
88@@ -77,57 +79,59 @@ scan_month_abbrev(const gchar **buf, gint *left, gint *mon)
89 {
90 *mon = -1;
91
92- if (*left < 3)
93+ const gsize abbrev_length = 3;
94+
95+ if (*left < abbrev_length)
96 return FALSE;
97
98 switch (**buf)
99 {
100 case 'J':
101- if (strncasecmp(*buf, "Jan", 3) == 0)
102+ if (strncasecmp(*buf, "Jan", abbrev_length) == 0)
103 *mon = 0;
104- else if (strncasecmp(*buf, "Jun", 3) == 0)
105+ else if (strncasecmp(*buf, "Jun", abbrev_length) == 0)
106 *mon = 5;
107- else if (strncasecmp(*buf, "Jul", 3) == 0)
108+ else if (strncasecmp(*buf, "Jul", abbrev_length) == 0)
109 *mon = 6;
110 break;
111 case 'F':
112- if (strncasecmp(*buf, "Feb", 3) == 0)
113+ if (strncasecmp(*buf, "Feb", abbrev_length) == 0)
114 *mon = 1;
115 break;
116 case 'M':
117- if (strncasecmp(*buf, "Mar", 3) == 0)
118+ if (strncasecmp(*buf, "Mar", abbrev_length) == 0)
119 *mon = 2;
120- else if (strncasecmp(*buf, "May", 3) == 0)
121+ else if (strncasecmp(*buf, "May", abbrev_length) == 0)
122 *mon = 4;
123 break;
124 case 'A':
125- if (strncasecmp(*buf, "Apr", 3) == 0)
126+ if (strncasecmp(*buf, "Apr", abbrev_length) == 0)
127 *mon = 3;
128- else if (strncasecmp(*buf, "Aug", 3) == 0)
129+ else if (strncasecmp(*buf, "Aug", abbrev_length) == 0)
130 *mon = 7;
131 break;
132 case 'S':
133- if (strncasecmp(*buf, "Sep", 3) == 0)
134+ if (strncasecmp(*buf, "Sep", abbrev_length) == 0)
135 *mon = 8;
136 break;
137 case 'O':
138- if (strncasecmp(*buf, "Oct", 3) == 0)
139+ if (strncasecmp(*buf, "Oct", abbrev_length) == 0)
140 *mon = 9;
141 break;
142 case 'N':
143- if (strncasecmp(*buf, "Nov", 3) == 0)
144+ if (strncasecmp(*buf, "Nov", abbrev_length) == 0)
145 *mon = 10;
146 break;
147 case 'D':
148- if (strncasecmp(*buf, "Dec", 3) == 0)
149+ if (strncasecmp(*buf, "Dec", abbrev_length) == 0)
150 *mon = 11;
151 break;
152 default:
153 return FALSE;
154 }
155
156- (*buf) += 3;
157- (*left) -= 3;
158+ (*buf) += abbrev_length;
159+ (*left) -= abbrev_length;
160 return TRUE;
161 }
162
163@@ -302,7 +306,7 @@ __parse_usec(const guchar **data, gint *length)
164 src++;
165 (*length)--;
166 }
167- while (isdigit(*src))
168+ while (*length > 0 && isdigit(*src))
169 {
170 src++;
171 (*length)--;
172@@ -316,19 +320,21 @@ __parse_usec(const guchar **data, gint *length)
173 static gboolean
174 __has_iso_timezone(const guchar *src, gint length)
175 {
176- return (length >= 5) &&
177+ return (length >= 6) &&
178 (*src == '+' || *src == '-') &&
179 isdigit(*(src+1)) &&
180 isdigit(*(src+2)) &&
181 *(src+3) == ':' &&
182 isdigit(*(src+4)) &&
183 isdigit(*(src+5)) &&
184- !isdigit(*(src+6));
185+ (length < 7 || !isdigit(*(src+6)));
186 }
187
188 static guint32
189 __parse_iso_timezone(const guchar **data, gint *length)
190 {
191+ g_assert(*length >= 6);
192+
193 gint hours, mins;
194 const guchar *src = *data;
195 guint32 tz = 0;
196@@ -338,8 +344,10 @@ __parse_iso_timezone(const guchar **data, gint *length)
197 hours = (*(src + 1) - '0') * 10 + *(src + 2) - '0';
198 mins = (*(src + 4) - '0') * 10 + *(src + 5) - '0';
199 tz = sign * (hours * 3600 + mins * 60);
200+
201 src += 6;
202 (*length) -= 6;
203+
204 *data = src;
205 return tz;
206 }
207@@ -393,7 +401,7 @@ __parse_bsd_timestamp(const guchar **data, gint *length, WallClockTime *wct)
208 if (!scan_pix_timestamp((const gchar **) &src, &left, wct))
209 return FALSE;
210
211- if (*src == ':')
212+ if (left && *src == ':')
213 {
214 src++;
215 left--;
216@@ -444,7 +452,7 @@ scan_rfc3164_timestamp(const guchar **data, gint *length, WallClockTime *wct)
217 * looking at you, skip that as well, so we can reliably detect IPv6
218 * addresses as hostnames, which would be using ":" as well. */
219
220- if (*src == ':')
221+ if (left && *src == ':')
222 {
223 ++src;
224 --left;
225diff --git a/lib/timeutils/tests/test_scan-timestamp.c b/lib/timeutils/tests/test_scan-timestamp.c
226index 4508139..ad657c6 100644
227--- a/lib/timeutils/tests/test_scan-timestamp.c
228+++ b/lib/timeutils/tests/test_scan-timestamp.c
229@@ -49,17 +49,21 @@ fake_time_add(time_t diff)
230 }
231
232 static gboolean
233-_parse_rfc3164(const gchar *ts, gchar isotimestamp[32])
234+_parse_rfc3164(const gchar *ts, gint len, gchar isotimestamp[32])
235 {
236 UnixTime stamp;
237- const guchar *data = (const guchar *) ts;
238- gint length = strlen(ts);
239+ const guchar *tsu = (const guchar *) ts;
240+ gint tsu_len = len < 0 ? strlen(ts) : len;
241 GString *result = g_string_new("");
242 WallClockTime wct = WALL_CLOCK_TIME_INIT;
243
244-
245+ const guchar *data = tsu;
246+ gint length = tsu_len;
247 gboolean success = scan_rfc3164_timestamp(&data, &length, &wct);
248
249+ cr_assert(length >= 0);
250+ cr_assert(data == &tsu[tsu_len - length]);
251+
252 unix_time_unset(&stamp);
253 convert_wall_clock_time_to_unix_time(&wct, &stamp);
254
255@@ -70,16 +74,21 @@ _parse_rfc3164(const gchar *ts, gchar isotimestamp[32])
256 }
257
258 static gboolean
259-_parse_rfc5424(const gchar *ts, gchar isotimestamp[32])
260+_parse_rfc5424(const gchar *ts, gint len, gchar isotimestamp[32])
261 {
262 UnixTime stamp;
263- const guchar *data = (const guchar *) ts;
264- gint length = strlen(ts);
265+ const guchar *tsu = (const guchar *) ts;
266+ gint tsu_len = len < 0 ? strlen(ts) : len;
267 GString *result = g_string_new("");
268 WallClockTime wct = WALL_CLOCK_TIME_INIT;
269
270+ const guchar *data = tsu;
271+ gint length = tsu_len;
272 gboolean success = scan_rfc5424_timestamp(&data, &length, &wct);
273
274+ cr_assert(length >= 0);
275+ cr_assert(data == &tsu[tsu_len - length]);
276+
277 unix_time_unset(&stamp);
278 convert_wall_clock_time_to_unix_time(&wct, &stamp);
279
280@@ -90,31 +99,60 @@ _parse_rfc5424(const gchar *ts, gchar isotimestamp[32])
281 }
282
283 static gboolean
284-_rfc3164_timestamp_eq(const gchar *ts, const gchar *expected, gchar converted[32])
285+_rfc3164_timestamp_eq(const gchar *ts, gint len, const gchar *expected, gchar converted[32])
286 {
287- cr_assert(_parse_rfc3164(ts, converted));
288+ cr_assert(_parse_rfc3164(ts, len, converted));
289 return strcmp(converted, expected) == 0;
290 }
291
292 static gboolean
293-_rfc5424_timestamp_eq(const gchar *ts, const gchar *expected, gchar converted[32])
294+_rfc5424_timestamp_eq(const gchar *ts, gint len, const gchar *expected, gchar converted[32])
295 {
296- cr_assert(_parse_rfc5424(ts, converted));
297+ cr_assert(_parse_rfc5424(ts, len, converted));
298 return strcmp(converted, expected) == 0;
299 }
300
301 #define _expect_rfc3164_timestamp_eq(ts, expected) \
302 ({ \
303 gchar converted[32]; \
304- cr_expect(_rfc3164_timestamp_eq(ts, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
305+ cr_expect(_rfc3164_timestamp_eq(ts, -1, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
306+ })
307+
308+#define _expect_rfc3164_timestamp_len_eq(ts, len, expected) \
309+ ({ \
310+ gchar converted[32]; \
311+ cr_expect(_rfc3164_timestamp_eq(ts, len, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
312+ })
313+
314+#define _expect_rfc3164_fails(ts, len) \
315+ ({ \
316+ WallClockTime wct = WALL_CLOCK_TIME_INIT; \
317+ const guchar *data = (guchar *) ts; \
318+ gint length = len < 0 ? strlen(ts) : len; \
319+ cr_assert_not(scan_rfc3164_timestamp(&data, &length, &wct)); \
320 })
321
322 #define _expect_rfc5424_timestamp_eq(ts, expected) \
323 ({ \
324 gchar converted[32]; \
325- cr_expect(_rfc5424_timestamp_eq(ts, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
326+ cr_expect(_rfc5424_timestamp_eq(ts, -1, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
327+ })
328+
329+#define _expect_rfc5424_timestamp_len_eq(ts, len, expected) \
330+ ({ \
331+ gchar converted[32]; \
332+ cr_expect(_rfc5424_timestamp_eq(ts, len, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
333 })
334
335+#define _expect_rfc5424_fails(ts, len) \
336+ ({ \
337+ WallClockTime wct = WALL_CLOCK_TIME_INIT; \
338+ const guchar *data = (guchar *) ts; \
339+ gint length = len < 0 ? strlen(ts) : len; \
340+ cr_assert_not(scan_rfc5424_timestamp(&data, &length, &wct)); \
341+ })
342+
343+
344 Test(parse_timestamp, standard_bsd_format)
345 {
346 _expect_rfc3164_timestamp_eq("Oct 1 17:46:12", "2017-10-01T17:46:12.000+02:00");
347@@ -148,6 +186,75 @@ Test(parse_timestamp, standard_bsd_format_year_in_the_past)
348 _expect_rfc3164_timestamp_eq("Dec 31 17:46:12", "2017-12-31T17:46:12.000+01:00");
349 }
350
351+Test(parse_timestamp, non_zero_terminated_rfc3164_iso_input_is_handled_properly)
352+{
353+ gchar *ts = "2022-08-17T05:02:28.417Z whatever";
354+ gint ts_len = 24;
355+
356+ _expect_rfc3164_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.417+00:00");
357+ _expect_rfc3164_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.417+00:00");
358+ _expect_rfc3164_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.417+00:00");
359+
360+ /* no "Z" parsed, timezone defaults to local, forced CET */
361+ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 1, "2022-08-17T05:02:28.417+02:00");
362+
363+ /* msec is partially parsed as we trim the string from the right */
364+ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 2, "2022-08-17T05:02:28.410+02:00");
365+ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 3, "2022-08-17T05:02:28.400+02:00");
366+ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 4, "2022-08-17T05:02:28.000+02:00");
367+ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 5, "2022-08-17T05:02:28.000+02:00");
368+
369+ for (gint i = 6; i < ts_len; i++)
370+ _expect_rfc3164_fails(ts, ts_len - i);
371+
372+}
373+
374+Test(parse_timestamp, non_zero_terminated_rfc3164_bsd_pix_or_asa_input_is_handled_properly)
375+{
376+ gchar *ts = "Aug 17 2022 05:02:28: whatever";
377+ gint ts_len = 21;
378+
379+ _expect_rfc3164_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.000+02:00");
380+ _expect_rfc3164_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.000+02:00");
381+ _expect_rfc3164_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.000+02:00");
382+
383+ /* no ":" at the end, that's a problem, unrecognized */
384+ _expect_rfc3164_fails(ts, ts_len - 1);
385+
386+ for (gint i = 1; i < ts_len; i++)
387+ _expect_rfc3164_fails(ts, ts_len - i);
388+}
389+
390+Test(parse_timestamp, non_zero_terminated_rfc5424_input_is_handled_properly)
391+{
392+ gchar *ts = "2022-08-17T05:02:28.417Z whatever";
393+ gint ts_len = 24;
394+
395+ _expect_rfc5424_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.417+00:00");
396+ _expect_rfc5424_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.417+00:00");
397+ _expect_rfc5424_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.417+00:00");
398+
399+ /* no "Z" parsed, timezone defaults to local, forced CET */
400+ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 1, "2022-08-17T05:02:28.417+02:00");
401+
402+ /* msec is partially parsed as we trim the string from the right */
403+ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 2, "2022-08-17T05:02:28.410+02:00");
404+ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 3, "2022-08-17T05:02:28.400+02:00");
405+ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 4, "2022-08-17T05:02:28.000+02:00");
406+ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 5, "2022-08-17T05:02:28.000+02:00");
407+
408+ for (gint i = 6; i < ts_len; i++)
409+ _expect_rfc5424_fails(ts, ts_len - i);
410+
411+}
412+
413+Test(parse_timestamp, non_zero_terminated_rfc5424_timestamp_only)
414+{
415+ const gchar *ts = "2022-08-17T05:02:28.417+03:00";
416+ gint ts_len = strlen(ts);
417+ _expect_rfc5424_timestamp_len_eq(ts, ts_len, ts);
418+}
419+
420
421 Test(parse_timestamp, daylight_saving_behavior_at_spring_with_explicit_timezones)
422 {
423diff --git a/modules/syslogformat/CMakeLists.txt b/modules/syslogformat/CMakeLists.txt
424index fb55ea4..a2a92bb 100644
425--- a/modules/syslogformat/CMakeLists.txt
426+++ b/modules/syslogformat/CMakeLists.txt
427@@ -24,4 +24,6 @@ target_include_directories(syslogformat
428 )
429 target_link_libraries(syslogformat PRIVATE syslog-ng)
430
431+add_test_subdirectory(tests)
432+
433 install(TARGETS syslogformat LIBRARY DESTINATION lib/syslog-ng/)
434diff --git a/modules/syslogformat/Makefile.am b/modules/syslogformat/Makefile.am
435index f13f88c..14cdf58 100644
436--- a/modules/syslogformat/Makefile.am
437+++ b/modules/syslogformat/Makefile.am
438@@ -31,3 +31,5 @@ modules_syslogformat_libsyslogformat_la_DEPENDENCIES = \
439 modules/syslogformat modules/syslogformat/ mod-syslogformat: \
440 modules/syslogformat/libsyslogformat.la
441 .PHONY: modules/syslogformat/ mod-syslogformat
442+
443+include modules/syslogformat/tests/Makefile.am
444diff --git a/modules/syslogformat/syslog-format.c b/modules/syslogformat/syslog-format.c
445index 6d53a32..a69f39f 100644
446--- a/modules/syslogformat/syslog-format.c
447+++ b/modules/syslogformat/syslog-format.c
448@@ -200,7 +200,7 @@ log_msg_parse_cisco_sequence_id(LogMessage *self, const guchar **data, gint *len
449
450 /* if the next char is not space, then we may try to read a date */
451
452- if (*src != ' ')
453+ if (!left || *src != ' ')
454 return;
455
456 log_msg_set_value(self, handles.cisco_seqid, (gchar *) *data, *length - left - 1);
457@@ -216,6 +216,9 @@ log_msg_parse_cisco_timestamp_attributes(LogMessage *self, const guchar **data,
458 const guchar *src = *data;
459 gint left = *length;
460
461+ if (!left)
462+ return;
463+
464 /* Cisco timestamp extensions, the first '*' indicates that the clock is
465 * unsynced, '.' if it is known to be synced */
466 if (G_UNLIKELY(src[0] == '*'))
467@@ -564,7 +567,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF
468 open_sd++;
469 do
470 {
471- if (!isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
472+ if (!left || !isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
473 goto error;
474 /* read sd_id */
475 pos = 0;
476@@ -598,7 +601,8 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF
477 strcpy(sd_value_name, logmsg_sd_prefix);
478 /* this strcat is safe, as sd_id_name is at most 32 chars */
479 strncpy(sd_value_name + logmsg_sd_prefix_len, sd_id_name, sizeof(sd_value_name) - logmsg_sd_prefix_len);
480- if (*src == ']')
481+
482+ if (left && *src == ']')
483 {
484 log_msg_set_value_by_name(self, sd_value_name, "", 0);
485 }
486@@ -615,7 +619,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF
487 else
488 goto error;
489
490- if (!isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
491+ if (!left || !isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
492 goto error;
493
494 /* read sd-param */
495diff --git a/modules/syslogformat/tests/CMakeLists.txt b/modules/syslogformat/tests/CMakeLists.txt
496new file mode 100644
497index 0000000..2e45b71
498--- /dev/null
499+++ b/modules/syslogformat/tests/CMakeLists.txt
500@@ -0,0 +1 @@
501+add_unit_test(CRITERION TARGET test_syslog_format DEPENDS syslogformat)
502diff --git a/modules/syslogformat/tests/Makefile.am b/modules/syslogformat/tests/Makefile.am
503new file mode 100644
504index 0000000..7ee66a5
505--- /dev/null
506+++ b/modules/syslogformat/tests/Makefile.am
507@@ -0,0 +1,9 @@
508+modules_syslogformat_tests_TESTS = \
509+ modules/syslogformat/tests/test_syslog_format
510+
511+check_PROGRAMS += ${modules_syslogformat_tests_TESTS}
512+
513+EXTRA_DIST += modules/syslogformat/tests/CMakeLists.txt
514+
515+modules_syslogformat_tests_test_syslog_format_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/syslogformat
516+modules_syslogformat_tests_test_syslog_format_LDADD = $(TEST_LDADD) $(PREOPEN_SYSLOGFORMAT)
517diff --git a/modules/syslogformat/tests/test_syslog_format.c b/modules/syslogformat/tests/test_syslog_format.c
518new file mode 100644
519index 0000000..d0f5b40
520--- /dev/null
521+++ b/modules/syslogformat/tests/test_syslog_format.c
522@@ -0,0 +1,104 @@
523+/*
524+ * Copyright (c) 2022 One Identity
525+ * Copyright (c) 2022 László Várady
526+ *
527+ * This program is free software; you can redistribute it and/or modify it
528+ * under the terms of the GNU General Public License version 2 as published
529+ * by the Free Software Foundation, or (at your option) any later version.
530+ *
531+ * This program is distributed in the hope that it will be useful,
532+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
533+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
534+ * GNU General Public License for more details.
535+ *
536+ * You should have received a copy of the GNU General Public License
537+ * along with this program; if not, write to the Free Software
538+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
539+ *
540+ * As an additional exemption you are allowed to compile & link against the
541+ * OpenSSL libraries as published by the OpenSSL project. See the file
542+ * COPYING for details.
543+ *
544+ */
545+
546+#include <criterion/criterion.h>
547+
548+#include "apphook.h"
549+#include "cfg.h"
550+#include "syslog-format.h"
551+#include "logmsg/logmsg.h"
552+#include "msg-format.h"
553+#include "scratch-buffers.h"
554+
555+#include <string.h>
556+
557+GlobalConfig *cfg;
558+MsgFormatOptions parse_options;
559+
560+static void
561+setup(void)
562+{
563+ app_startup();
564+ syslog_format_init();
565+
566+ cfg = cfg_new_snippet();
567+ msg_format_options_defaults(&parse_options);
568+}
569+
570+static void
571+teardown(void)
572+{
573+ scratch_buffers_explicit_gc();
574+ app_shutdown();
575+ cfg_free(cfg);
576+}
577+
578+TestSuite(syslog_format, .init = setup, .fini = teardown);
579+
580+Test(syslog_format, parser_should_not_spin_on_non_zero_terminated_input, .timeout = 10)
581+{
582+ const gchar *data = "<182>2022-08-17T05:02:28.217 mymachine su: 'su root' failed for lonvick on /dev/pts/8";
583+ /* chosen carefully to reproduce a bug */
584+ gsize data_length = 27;
585+
586+ msg_format_options_init(&parse_options, cfg);
587+ LogMessage *msg = msg_format_construct_message(&parse_options, (const guchar *) data, data_length);
588+
589+ gsize problem_position;
590+ cr_assert(syslog_format_handler(&parse_options, msg, (const guchar *) data, data_length, &problem_position));
591+
592+ msg_format_options_destroy(&parse_options);
593+ log_msg_unref(msg);
594+}
595+
596+Test(syslog_format, cisco_sequence_id_non_zero_termination)
597+{
598+ const gchar *data = "<189>65536: ";
599+ gsize data_length = strlen(data);
600+
601+ msg_format_options_init(&parse_options, cfg);
602+ LogMessage *msg = msg_format_construct_message(&parse_options, (const guchar *) data, data_length);
603+
604+ gsize problem_position;
605+ cr_assert(syslog_format_handler(&parse_options, msg, (const guchar *) data, data_length, &problem_position));
606+ cr_assert_str_eq(log_msg_get_value_by_name(msg, ".SDATA.meta.sequenceId", NULL), "65536");
607+
608+ msg_format_options_destroy(&parse_options);
609+ log_msg_unref(msg);
610+}
611+
612+Test(syslog_format, minimal_non_zero_terminated_numeric_message_is_parsed_as_program_name)
613+{
614+ const gchar *data = "<189>65536";
615+ gsize data_length = strlen(data);
616+
617+ msg_format_options_init(&parse_options, cfg);
618+ LogMessage *msg = msg_format_construct_message(&parse_options, (const guchar *) data, data_length);
619+
620+ gsize problem_position;
621+ cr_assert(syslog_format_handler(&parse_options, msg, (const guchar *) data, data_length, &problem_position));
622+ cr_assert_str_eq(log_msg_get_value_by_name(msg, "PROGRAM", NULL), "65536");
623+
624+ msg_format_options_destroy(&parse_options);
625+ log_msg_unref(msg);
626+}
627--
6282.25.1
629
diff --git a/meta-oe/recipes-support/syslog-ng/syslog-ng_3.24.1.bb b/meta-oe/recipes-support/syslog-ng/syslog-ng_3.24.1.bb
index 10bf00fdce..6e90dabd14 100644
--- a/meta-oe/recipes-support/syslog-ng/syslog-ng_3.24.1.bb
+++ b/meta-oe/recipes-support/syslog-ng/syslog-ng_3.24.1.bb
@@ -9,6 +9,7 @@ SRC_URI += " \
9 file://0001-syslog-ng-fix-segment-fault-during-service-start.patch \ 9 file://0001-syslog-ng-fix-segment-fault-during-service-start.patch \
10 file://shebang.patch \ 10 file://shebang.patch \
11 file://syslog-ng-tmp.conf \ 11 file://syslog-ng-tmp.conf \
12 file://CVE-2022-38725.patch \
12 " 13 "
13 14
14SRC_URI[md5sum] = "ef9de066793f7358af7312b964ac0450" 15SRC_URI[md5sum] = "ef9de066793f7358af7312b964ac0450"