From patchwork Fri Mar 31 04:47:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hitendra Prajapati X-Patchwork-Id: 21982 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32882C6FD18 for ; Fri, 31 Mar 2023 04:47:46 +0000 (UTC) Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) by mx.groups.io with SMTP id smtpd.web11.47489.1680238062439492414 for ; Thu, 30 Mar 2023 21:47:42 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@mvista.com header.s=google header.b=D4T+gbmU; spf=pass (domain: mvista.com, ip: 209.85.216.48, mailfrom: hprajapati@mvista.com) Received: by mail-pj1-f48.google.com with SMTP id p3-20020a17090a74c300b0023f69bc7a68so22125744pjl.4 for ; Thu, 30 Mar 2023 21:47:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mvista.com; s=google; t=1680238061; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=NgJv+XNPLAJ3weXr8VvH0FvWitWn4ZZcdXU6HAeZk1s=; b=D4T+gbmUOAZWOzzR8l8HFdMbcQn9bycAYwvUhuf6bS46Ct8TAMtjlM1SgcV6OOlnBm GSHqqR8Iqrd7mgLfUJJlXKN/ak3IvGghmVrZOSiDyBtAyo6v9qaDxBAQDXka8BvsbsIm U6UhfpiUYgaUxFVZpKd+SQdtD92B+Hf06Ph90= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680238061; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=NgJv+XNPLAJ3weXr8VvH0FvWitWn4ZZcdXU6HAeZk1s=; b=kDpTOMU6s0jCukJGDg3sndlRieWiFwF8/RM9Xb3AaX0g+6D+HdXrVeDuUD+FWXGfC0 kGkNa1C2cAWes0BWeM81Ev373DQO9LmknoTEF7/n+WB3AyGAJR4hEpY6LLHV7a6kctmt gFIAcnXBaq/DeuWXHaPIZxHsGOOdBOR5oXzU7beyTlWbvkzwJV/HjX/beMaQdq3+F7T7 +2WewK1ex3XBhkxXXTwGcUyN/lDeUTXzK4caxGzgNAKL5A4sos5KR5tFIG6aWD7ohLXk SOBeBr6mgMy78tmdQx39j6g/uQ39x4oZknlTVdNjLE30lwl8V2bYTzE4HpjTp+QJXHWS l9DQ== X-Gm-Message-State: AAQBX9eGF1y6xDmZOnNsjdFd3qvrO64Y9fNVHPbF7doxD1Y6VIIgdZKP sQY3t6JrRVL/7ymWHxg61wTANtxliHOgxu8fiF8= X-Google-Smtp-Source: AKy350akRiYZbiyvqqF74NsoStW7Y7145qom6kNoC/ZrSLbylMb7oIRp62kt7kJARpCQM4C8CCEThQ== X-Received: by 2002:a17:902:ecc2:b0:19a:b754:4053 with SMTP id a2-20020a170902ecc200b0019ab7544053mr34205658plh.26.1680238061116; Thu, 30 Mar 2023 21:47:41 -0700 (PDT) Received: from MVIN00024 ([103.250.136.233]) by smtp.gmail.com with ESMTPSA id g24-20020a1709029f9800b00198f256a192sm539375plq.171.2023.03.30.21.47.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Mar 2023 21:47:40 -0700 (PDT) Received: by MVIN00024 (sSMTP sendmail emulation); Fri, 31 Mar 2023 10:17:35 +0530 From: Hitendra Prajapati To: openembedded-devel@lists.openembedded.org Cc: Hitendra Prajapati Subject: [meta-oe][dunfell][PATCH] syslog-ng: CVE-2022-38725 An integer overflow in the RFC3164 parser Date: Fri, 31 Mar 2023 10:17:32 +0530 Message-Id: <20230331044732.6682-1-hprajapati@mvista.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Fri, 31 Mar 2023 04:47:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/101847 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 --- .../syslog-ng/files/CVE-2022-38725.patch | 629 ++++++++++++++++++ .../syslog-ng/syslog-ng_3.24.1.bb | 1 + 2 files changed, 630 insertions(+) create mode 100644 meta-oe/recipes-support/syslog-ng/files/CVE-2022-38725.patch 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 @@ +From 73b5c300b8fde5e7a4824baa83a04931279abb37 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?L=C3=A1szl=C3=B3=20V=C3=A1rady?= + +Date: Sat, 20 Aug 2022 12:42:38 +0200 +Subject: [PATCH] CVE-2022-38725 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: László Várady +Signed-off-by: Balazs Scheidler + +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] +CVE: CVE-2022-38725 +Signed-off-by: Hitendra Prajapati +--- + lib/timeutils/scan-timestamp.c | 68 +++++---- + lib/timeutils/tests/test_scan-timestamp.c | 133 ++++++++++++++++-- + modules/syslogformat/CMakeLists.txt | 2 + + modules/syslogformat/Makefile.am | 2 + + modules/syslogformat/syslog-format.c | 12 +- + modules/syslogformat/tests/CMakeLists.txt | 1 + + modules/syslogformat/tests/Makefile.am | 9 ++ + .../syslogformat/tests/test_syslog_format.c | 104 ++++++++++++++ + 8 files changed, 284 insertions(+), 47 deletions(-) + create mode 100644 modules/syslogformat/tests/CMakeLists.txt + create mode 100644 modules/syslogformat/tests/Makefile.am + create mode 100644 modules/syslogformat/tests/test_syslog_format.c + +diff --git a/lib/timeutils/scan-timestamp.c b/lib/timeutils/scan-timestamp.c +index 41ead1a..ec9746b 100644 +--- a/lib/timeutils/scan-timestamp.c ++++ b/lib/timeutils/scan-timestamp.c +@@ -34,41 +34,43 @@ scan_day_abbrev(const gchar **buf, gint *left, gint *wday) + { + *wday = -1; + +- if (*left < 3) ++ const gsize abbrev_length = 3; ++ ++ if (*left < abbrev_length) + return FALSE; + + switch (**buf) + { + case 'S': +- if (strncasecmp(*buf, "Sun", 3) == 0) ++ if (strncasecmp(*buf, "Sun", abbrev_length) == 0) + *wday = 0; +- else if (strncasecmp(*buf, "Sat", 3) == 0) ++ else if (strncasecmp(*buf, "Sat", abbrev_length) == 0) + *wday = 6; + break; + case 'M': +- if (strncasecmp(*buf, "Mon", 3) == 0) ++ if (strncasecmp(*buf, "Mon", abbrev_length) == 0) + *wday = 1; + break; + case 'T': +- if (strncasecmp(*buf, "Tue", 3) == 0) ++ if (strncasecmp(*buf, "Tue", abbrev_length) == 0) + *wday = 2; +- else if (strncasecmp(*buf, "Thu", 3) == 0) ++ else if (strncasecmp(*buf, "Thu", abbrev_length) == 0) + *wday = 4; + break; + case 'W': +- if (strncasecmp(*buf, "Wed", 3) == 0) ++ if (strncasecmp(*buf, "Wed", abbrev_length) == 0) + *wday = 3; + break; + case 'F': +- if (strncasecmp(*buf, "Fri", 3) == 0) ++ if (strncasecmp(*buf, "Fri", abbrev_length) == 0) + *wday = 5; + break; + default: + return FALSE; + } + +- (*buf) += 3; +- (*left) -= 3; ++ (*buf) += abbrev_length; ++ (*left) -= abbrev_length; + return TRUE; + } + +@@ -77,57 +79,59 @@ scan_month_abbrev(const gchar **buf, gint *left, gint *mon) + { + *mon = -1; + +- if (*left < 3) ++ const gsize abbrev_length = 3; ++ ++ if (*left < abbrev_length) + return FALSE; + + switch (**buf) + { + case 'J': +- if (strncasecmp(*buf, "Jan", 3) == 0) ++ if (strncasecmp(*buf, "Jan", abbrev_length) == 0) + *mon = 0; +- else if (strncasecmp(*buf, "Jun", 3) == 0) ++ else if (strncasecmp(*buf, "Jun", abbrev_length) == 0) + *mon = 5; +- else if (strncasecmp(*buf, "Jul", 3) == 0) ++ else if (strncasecmp(*buf, "Jul", abbrev_length) == 0) + *mon = 6; + break; + case 'F': +- if (strncasecmp(*buf, "Feb", 3) == 0) ++ if (strncasecmp(*buf, "Feb", abbrev_length) == 0) + *mon = 1; + break; + case 'M': +- if (strncasecmp(*buf, "Mar", 3) == 0) ++ if (strncasecmp(*buf, "Mar", abbrev_length) == 0) + *mon = 2; +- else if (strncasecmp(*buf, "May", 3) == 0) ++ else if (strncasecmp(*buf, "May", abbrev_length) == 0) + *mon = 4; + break; + case 'A': +- if (strncasecmp(*buf, "Apr", 3) == 0) ++ if (strncasecmp(*buf, "Apr", abbrev_length) == 0) + *mon = 3; +- else if (strncasecmp(*buf, "Aug", 3) == 0) ++ else if (strncasecmp(*buf, "Aug", abbrev_length) == 0) + *mon = 7; + break; + case 'S': +- if (strncasecmp(*buf, "Sep", 3) == 0) ++ if (strncasecmp(*buf, "Sep", abbrev_length) == 0) + *mon = 8; + break; + case 'O': +- if (strncasecmp(*buf, "Oct", 3) == 0) ++ if (strncasecmp(*buf, "Oct", abbrev_length) == 0) + *mon = 9; + break; + case 'N': +- if (strncasecmp(*buf, "Nov", 3) == 0) ++ if (strncasecmp(*buf, "Nov", abbrev_length) == 0) + *mon = 10; + break; + case 'D': +- if (strncasecmp(*buf, "Dec", 3) == 0) ++ if (strncasecmp(*buf, "Dec", abbrev_length) == 0) + *mon = 11; + break; + default: + return FALSE; + } + +- (*buf) += 3; +- (*left) -= 3; ++ (*buf) += abbrev_length; ++ (*left) -= abbrev_length; + return TRUE; + } + +@@ -302,7 +306,7 @@ __parse_usec(const guchar **data, gint *length) + src++; + (*length)--; + } +- while (isdigit(*src)) ++ while (*length > 0 && isdigit(*src)) + { + src++; + (*length)--; +@@ -316,19 +320,21 @@ __parse_usec(const guchar **data, gint *length) + static gboolean + __has_iso_timezone(const guchar *src, gint length) + { +- return (length >= 5) && ++ return (length >= 6) && + (*src == '+' || *src == '-') && + isdigit(*(src+1)) && + isdigit(*(src+2)) && + *(src+3) == ':' && + isdigit(*(src+4)) && + isdigit(*(src+5)) && +- !isdigit(*(src+6)); ++ (length < 7 || !isdigit(*(src+6))); + } + + static guint32 + __parse_iso_timezone(const guchar **data, gint *length) + { ++ g_assert(*length >= 6); ++ + gint hours, mins; + const guchar *src = *data; + guint32 tz = 0; +@@ -338,8 +344,10 @@ __parse_iso_timezone(const guchar **data, gint *length) + hours = (*(src + 1) - '0') * 10 + *(src + 2) - '0'; + mins = (*(src + 4) - '0') * 10 + *(src + 5) - '0'; + tz = sign * (hours * 3600 + mins * 60); ++ + src += 6; + (*length) -= 6; ++ + *data = src; + return tz; + } +@@ -393,7 +401,7 @@ __parse_bsd_timestamp(const guchar **data, gint *length, WallClockTime *wct) + if (!scan_pix_timestamp((const gchar **) &src, &left, wct)) + return FALSE; + +- if (*src == ':') ++ if (left && *src == ':') + { + src++; + left--; +@@ -444,7 +452,7 @@ scan_rfc3164_timestamp(const guchar **data, gint *length, WallClockTime *wct) + * looking at you, skip that as well, so we can reliably detect IPv6 + * addresses as hostnames, which would be using ":" as well. */ + +- if (*src == ':') ++ if (left && *src == ':') + { + ++src; + --left; +diff --git a/lib/timeutils/tests/test_scan-timestamp.c b/lib/timeutils/tests/test_scan-timestamp.c +index 4508139..ad657c6 100644 +--- a/lib/timeutils/tests/test_scan-timestamp.c ++++ b/lib/timeutils/tests/test_scan-timestamp.c +@@ -49,17 +49,21 @@ fake_time_add(time_t diff) + } + + static gboolean +-_parse_rfc3164(const gchar *ts, gchar isotimestamp[32]) ++_parse_rfc3164(const gchar *ts, gint len, gchar isotimestamp[32]) + { + UnixTime stamp; +- const guchar *data = (const guchar *) ts; +- gint length = strlen(ts); ++ const guchar *tsu = (const guchar *) ts; ++ gint tsu_len = len < 0 ? strlen(ts) : len; + GString *result = g_string_new(""); + WallClockTime wct = WALL_CLOCK_TIME_INIT; + +- ++ const guchar *data = tsu; ++ gint length = tsu_len; + gboolean success = scan_rfc3164_timestamp(&data, &length, &wct); + ++ cr_assert(length >= 0); ++ cr_assert(data == &tsu[tsu_len - length]); ++ + unix_time_unset(&stamp); + convert_wall_clock_time_to_unix_time(&wct, &stamp); + +@@ -70,16 +74,21 @@ _parse_rfc3164(const gchar *ts, gchar isotimestamp[32]) + } + + static gboolean +-_parse_rfc5424(const gchar *ts, gchar isotimestamp[32]) ++_parse_rfc5424(const gchar *ts, gint len, gchar isotimestamp[32]) + { + UnixTime stamp; +- const guchar *data = (const guchar *) ts; +- gint length = strlen(ts); ++ const guchar *tsu = (const guchar *) ts; ++ gint tsu_len = len < 0 ? strlen(ts) : len; + GString *result = g_string_new(""); + WallClockTime wct = WALL_CLOCK_TIME_INIT; + ++ const guchar *data = tsu; ++ gint length = tsu_len; + gboolean success = scan_rfc5424_timestamp(&data, &length, &wct); + ++ cr_assert(length >= 0); ++ cr_assert(data == &tsu[tsu_len - length]); ++ + unix_time_unset(&stamp); + convert_wall_clock_time_to_unix_time(&wct, &stamp); + +@@ -90,31 +99,60 @@ _parse_rfc5424(const gchar *ts, gchar isotimestamp[32]) + } + + static gboolean +-_rfc3164_timestamp_eq(const gchar *ts, const gchar *expected, gchar converted[32]) ++_rfc3164_timestamp_eq(const gchar *ts, gint len, const gchar *expected, gchar converted[32]) + { +- cr_assert(_parse_rfc3164(ts, converted)); ++ cr_assert(_parse_rfc3164(ts, len, converted)); + return strcmp(converted, expected) == 0; + } + + static gboolean +-_rfc5424_timestamp_eq(const gchar *ts, const gchar *expected, gchar converted[32]) ++_rfc5424_timestamp_eq(const gchar *ts, gint len, const gchar *expected, gchar converted[32]) + { +- cr_assert(_parse_rfc5424(ts, converted)); ++ cr_assert(_parse_rfc5424(ts, len, converted)); + return strcmp(converted, expected) == 0; + } + + #define _expect_rfc3164_timestamp_eq(ts, expected) \ + ({ \ + gchar converted[32]; \ +- cr_expect(_rfc3164_timestamp_eq(ts, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \ ++ 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); \ ++ }) ++ ++#define _expect_rfc3164_timestamp_len_eq(ts, len, expected) \ ++ ({ \ ++ gchar converted[32]; \ ++ 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); \ ++ }) ++ ++#define _expect_rfc3164_fails(ts, len) \ ++ ({ \ ++ WallClockTime wct = WALL_CLOCK_TIME_INIT; \ ++ const guchar *data = (guchar *) ts; \ ++ gint length = len < 0 ? strlen(ts) : len; \ ++ cr_assert_not(scan_rfc3164_timestamp(&data, &length, &wct)); \ + }) + + #define _expect_rfc5424_timestamp_eq(ts, expected) \ + ({ \ + gchar converted[32]; \ +- cr_expect(_rfc5424_timestamp_eq(ts, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \ ++ 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); \ ++ }) ++ ++#define _expect_rfc5424_timestamp_len_eq(ts, len, expected) \ ++ ({ \ ++ gchar converted[32]; \ ++ 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); \ + }) + ++#define _expect_rfc5424_fails(ts, len) \ ++ ({ \ ++ WallClockTime wct = WALL_CLOCK_TIME_INIT; \ ++ const guchar *data = (guchar *) ts; \ ++ gint length = len < 0 ? strlen(ts) : len; \ ++ cr_assert_not(scan_rfc5424_timestamp(&data, &length, &wct)); \ ++ }) ++ ++ + Test(parse_timestamp, standard_bsd_format) + { + _expect_rfc3164_timestamp_eq("Oct 1 17:46:12", "2017-10-01T17:46:12.000+02:00"); +@@ -148,6 +186,75 @@ Test(parse_timestamp, standard_bsd_format_year_in_the_past) + _expect_rfc3164_timestamp_eq("Dec 31 17:46:12", "2017-12-31T17:46:12.000+01:00"); + } + ++Test(parse_timestamp, non_zero_terminated_rfc3164_iso_input_is_handled_properly) ++{ ++ gchar *ts = "2022-08-17T05:02:28.417Z whatever"; ++ gint ts_len = 24; ++ ++ _expect_rfc3164_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.417+00:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.417+00:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.417+00:00"); ++ ++ /* no "Z" parsed, timezone defaults to local, forced CET */ ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 1, "2022-08-17T05:02:28.417+02:00"); ++ ++ /* msec is partially parsed as we trim the string from the right */ ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 2, "2022-08-17T05:02:28.410+02:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 3, "2022-08-17T05:02:28.400+02:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 4, "2022-08-17T05:02:28.000+02:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len - 5, "2022-08-17T05:02:28.000+02:00"); ++ ++ for (gint i = 6; i < ts_len; i++) ++ _expect_rfc3164_fails(ts, ts_len - i); ++ ++} ++ ++Test(parse_timestamp, non_zero_terminated_rfc3164_bsd_pix_or_asa_input_is_handled_properly) ++{ ++ gchar *ts = "Aug 17 2022 05:02:28: whatever"; ++ gint ts_len = 21; ++ ++ _expect_rfc3164_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.000+02:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.000+02:00"); ++ _expect_rfc3164_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.000+02:00"); ++ ++ /* no ":" at the end, that's a problem, unrecognized */ ++ _expect_rfc3164_fails(ts, ts_len - 1); ++ ++ for (gint i = 1; i < ts_len; i++) ++ _expect_rfc3164_fails(ts, ts_len - i); ++} ++ ++Test(parse_timestamp, non_zero_terminated_rfc5424_input_is_handled_properly) ++{ ++ gchar *ts = "2022-08-17T05:02:28.417Z whatever"; ++ gint ts_len = 24; ++ ++ _expect_rfc5424_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.417+00:00"); ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.417+00:00"); ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.417+00:00"); ++ ++ /* no "Z" parsed, timezone defaults to local, forced CET */ ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 1, "2022-08-17T05:02:28.417+02:00"); ++ ++ /* msec is partially parsed as we trim the string from the right */ ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 2, "2022-08-17T05:02:28.410+02:00"); ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 3, "2022-08-17T05:02:28.400+02:00"); ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 4, "2022-08-17T05:02:28.000+02:00"); ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len - 5, "2022-08-17T05:02:28.000+02:00"); ++ ++ for (gint i = 6; i < ts_len; i++) ++ _expect_rfc5424_fails(ts, ts_len - i); ++ ++} ++ ++Test(parse_timestamp, non_zero_terminated_rfc5424_timestamp_only) ++{ ++ const gchar *ts = "2022-08-17T05:02:28.417+03:00"; ++ gint ts_len = strlen(ts); ++ _expect_rfc5424_timestamp_len_eq(ts, ts_len, ts); ++} ++ + + Test(parse_timestamp, daylight_saving_behavior_at_spring_with_explicit_timezones) + { +diff --git a/modules/syslogformat/CMakeLists.txt b/modules/syslogformat/CMakeLists.txt +index fb55ea4..a2a92bb 100644 +--- a/modules/syslogformat/CMakeLists.txt ++++ b/modules/syslogformat/CMakeLists.txt +@@ -24,4 +24,6 @@ target_include_directories(syslogformat + ) + target_link_libraries(syslogformat PRIVATE syslog-ng) + ++add_test_subdirectory(tests) ++ + install(TARGETS syslogformat LIBRARY DESTINATION lib/syslog-ng/) +diff --git a/modules/syslogformat/Makefile.am b/modules/syslogformat/Makefile.am +index f13f88c..14cdf58 100644 +--- a/modules/syslogformat/Makefile.am ++++ b/modules/syslogformat/Makefile.am +@@ -31,3 +31,5 @@ modules_syslogformat_libsyslogformat_la_DEPENDENCIES = \ + modules/syslogformat modules/syslogformat/ mod-syslogformat: \ + modules/syslogformat/libsyslogformat.la + .PHONY: modules/syslogformat/ mod-syslogformat ++ ++include modules/syslogformat/tests/Makefile.am +diff --git a/modules/syslogformat/syslog-format.c b/modules/syslogformat/syslog-format.c +index 6d53a32..a69f39f 100644 +--- a/modules/syslogformat/syslog-format.c ++++ b/modules/syslogformat/syslog-format.c +@@ -200,7 +200,7 @@ log_msg_parse_cisco_sequence_id(LogMessage *self, const guchar **data, gint *len + + /* if the next char is not space, then we may try to read a date */ + +- if (*src != ' ') ++ if (!left || *src != ' ') + return; + + log_msg_set_value(self, handles.cisco_seqid, (gchar *) *data, *length - left - 1); +@@ -216,6 +216,9 @@ log_msg_parse_cisco_timestamp_attributes(LogMessage *self, const guchar **data, + const guchar *src = *data; + gint left = *length; + ++ if (!left) ++ return; ++ + /* Cisco timestamp extensions, the first '*' indicates that the clock is + * unsynced, '.' if it is known to be synced */ + if (G_UNLIKELY(src[0] == '*')) +@@ -564,7 +567,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF + open_sd++; + do + { +- if (!isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"') ++ if (!left || !isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"') + goto error; + /* read sd_id */ + pos = 0; +@@ -598,7 +601,8 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF + strcpy(sd_value_name, logmsg_sd_prefix); + /* this strcat is safe, as sd_id_name is at most 32 chars */ + strncpy(sd_value_name + logmsg_sd_prefix_len, sd_id_name, sizeof(sd_value_name) - logmsg_sd_prefix_len); +- if (*src == ']') ++ ++ if (left && *src == ']') + { + log_msg_set_value_by_name(self, sd_value_name, "", 0); + } +@@ -615,7 +619,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF + else + goto error; + +- if (!isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"') ++ if (!left || !isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"') + goto error; + + /* read sd-param */ +diff --git a/modules/syslogformat/tests/CMakeLists.txt b/modules/syslogformat/tests/CMakeLists.txt +new file mode 100644 +index 0000000..2e45b71 +--- /dev/null ++++ b/modules/syslogformat/tests/CMakeLists.txt +@@ -0,0 +1 @@ ++add_unit_test(CRITERION TARGET test_syslog_format DEPENDS syslogformat) +diff --git a/modules/syslogformat/tests/Makefile.am b/modules/syslogformat/tests/Makefile.am +new file mode 100644 +index 0000000..7ee66a5 +--- /dev/null ++++ b/modules/syslogformat/tests/Makefile.am +@@ -0,0 +1,9 @@ ++modules_syslogformat_tests_TESTS = \ ++ modules/syslogformat/tests/test_syslog_format ++ ++check_PROGRAMS += ${modules_syslogformat_tests_TESTS} ++ ++EXTRA_DIST += modules/syslogformat/tests/CMakeLists.txt ++ ++modules_syslogformat_tests_test_syslog_format_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/syslogformat ++modules_syslogformat_tests_test_syslog_format_LDADD = $(TEST_LDADD) $(PREOPEN_SYSLOGFORMAT) +diff --git a/modules/syslogformat/tests/test_syslog_format.c b/modules/syslogformat/tests/test_syslog_format.c +new file mode 100644 +index 0000000..d0f5b40 +--- /dev/null ++++ b/modules/syslogformat/tests/test_syslog_format.c +@@ -0,0 +1,104 @@ ++/* ++ * Copyright (c) 2022 One Identity ++ * Copyright (c) 2022 László Várady ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ * As an additional exemption you are allowed to compile & link against the ++ * OpenSSL libraries as published by the OpenSSL project. See the file ++ * COPYING for details. ++ * ++ */ ++ ++#include ++ ++#include "apphook.h" ++#include "cfg.h" ++#include "syslog-format.h" ++#include "logmsg/logmsg.h" ++#include "msg-format.h" ++#include "scratch-buffers.h" ++ ++#include ++ ++GlobalConfig *cfg; ++MsgFormatOptions parse_options; ++ ++static void ++setup(void) ++{ ++ app_startup(); ++ syslog_format_init(); ++ ++ cfg = cfg_new_snippet(); ++ msg_format_options_defaults(&parse_options); ++} ++ ++static void ++teardown(void) ++{ ++ scratch_buffers_explicit_gc(); ++ app_shutdown(); ++ cfg_free(cfg); ++} ++ ++TestSuite(syslog_format, .init = setup, .fini = teardown); ++ ++Test(syslog_format, parser_should_not_spin_on_non_zero_terminated_input, .timeout = 10) ++{ ++ const gchar *data = "<182>2022-08-17T05:02:28.217 mymachine su: 'su root' failed for lonvick on /dev/pts/8"; ++ /* chosen carefully to reproduce a bug */ ++ gsize data_length = 27; ++ ++ msg_format_options_init(&parse_options, cfg); ++ LogMessage *msg = msg_format_construct_message(&parse_options, (const guchar *) data, data_length); ++ ++ gsize problem_position; ++ cr_assert(syslog_format_handler(&parse_options, msg, (const guchar *) data, data_length, &problem_position)); ++ ++ msg_format_options_destroy(&parse_options); ++ log_msg_unref(msg); ++} ++ ++Test(syslog_format, cisco_sequence_id_non_zero_termination) ++{ ++ const gchar *data = "<189>65536: "; ++ gsize data_length = strlen(data); ++ ++ msg_format_options_init(&parse_options, cfg); ++ LogMessage *msg = msg_format_construct_message(&parse_options, (const guchar *) data, data_length); ++ ++ gsize problem_position; ++ cr_assert(syslog_format_handler(&parse_options, msg, (const guchar *) data, data_length, &problem_position)); ++ cr_assert_str_eq(log_msg_get_value_by_name(msg, ".SDATA.meta.sequenceId", NULL), "65536"); ++ ++ msg_format_options_destroy(&parse_options); ++ log_msg_unref(msg); ++} ++ ++Test(syslog_format, minimal_non_zero_terminated_numeric_message_is_parsed_as_program_name) ++{ ++ const gchar *data = "<189>65536"; ++ gsize data_length = strlen(data); ++ ++ msg_format_options_init(&parse_options, cfg); ++ LogMessage *msg = msg_format_construct_message(&parse_options, (const guchar *) data, data_length); ++ ++ gsize problem_position; ++ cr_assert(syslog_format_handler(&parse_options, msg, (const guchar *) data, data_length, &problem_position)); ++ cr_assert_str_eq(log_msg_get_value_by_name(msg, "PROGRAM", NULL), "65536"); ++ ++ msg_format_options_destroy(&parse_options); ++ log_msg_unref(msg); ++} +-- +2.25.1 + 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 += " \ file://0001-syslog-ng-fix-segment-fault-during-service-start.patch \ file://shebang.patch \ file://syslog-ng-tmp.conf \ + file://CVE-2022-38725.patch \ " SRC_URI[md5sum] = "ef9de066793f7358af7312b964ac0450"