Fixes: #12949
Signed-off-by: Michael Tremer <michael.tremer(a)ipfire.org>
---
lfs/glibc | 2 +
.../glibc-2.36-syslog-large-messages.patch | 336 ++++++++++++++++++
.../glibc-2.36-syslog-whitespace-fix.patch | 58 +++
3 files changed, 396 insertions(+)
create mode 100644 src/patches/glibc-2.36-syslog-large-messages.patch
create mode 100644 src/patches/glibc-2.36-syslog-whitespace-fix.patch
diff --git a/lfs/glibc b/lfs/glibc
index 798f3ed8a..b4dc7b7eb 100644
--- a/lfs/glibc
+++ b/lfs/glibc
@@ -112,6 +112,8 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@mkdir $(DIR_SRC)/glibc-build
cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-localedef-no-archive.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-2.36-syslog-large-messages.patch
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/glibc-2.36-syslog-whitespace-fix.patch
ifneq "$(TOOLCHAIN)" "1"
ifeq "$(BUILD_ARCH)" "x86_64"
diff --git a/src/patches/glibc-2.36-syslog-large-messages.patch b/src/patches/glibc-2.36-syslog-large-messages.patch
new file mode 100644
index 000000000..a490e7c59
--- /dev/null
+++ b/src/patches/glibc-2.36-syslog-large-messages.patch
@@ -0,0 +1,336 @@
+From b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella(a)linaro.org>
+Date: Sun, 28 Aug 2022 16:52:53 -0300
+Subject: [PATCH] syslog: Fix large messages (BZ#29536)
+
+The a583b6add407c17cd change did not handle large messages that
+would require a heap allocation correctly, where the message itself
+is not take in consideration.
+
+This patch fixes it and extend the tst-syslog to check for large
+messages as well.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh(a)sourceware.org>
+(cherry picked from commit 52a5be0df411ef3ff45c10c7c308cb92993d15b1)
+---
+ misc/syslog.c | 18 +++---
+ misc/tst-syslog.c | 152 +++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 142 insertions(+), 28 deletions(-)
+
+diff --git a/misc/syslog.c b/misc/syslog.c
+index 554089bfc4..b88f66c835 100644
+--- a/misc/syslog.c
++++ b/misc/syslog.c
+@@ -193,28 +193,32 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
+ int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
+ mode_flags);
+ if (0 <= vl && vl < sizeof bufs - l)
+- {
+- buf = bufs;
+- bufsize = l + vl;
+- }
++ buf = bufs;
++ bufsize = l + vl;
+
+ va_end (apc);
+ }
+
+ if (buf == NULL)
+ {
+- buf = malloc (l * sizeof (char));
++ buf = malloc ((bufsize + 1) * sizeof (char));
+ if (buf != NULL)
+ {
+ /* Tell the cancellation handler to free this buffer. */
+ clarg.buf = buf;
+
+ if (has_ts)
+- __snprintf (bufs, sizeof bufs,
++ __snprintf (buf, l + 1,
+ SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
+ else
+- __snprintf (bufs, sizeof bufs,
++ __snprintf (buf, l + 1,
+ SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
++
++ va_list apc;
++ va_copy (apc, ap);
++ __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
++ mode_flags);
++ va_end (apc);
+ }
+ else
+ {
+diff --git a/misc/tst-syslog.c b/misc/tst-syslog.c
+index e550d15796..1d332ece53 100644
+--- a/misc/tst-syslog.c
++++ b/misc/tst-syslog.c
+@@ -68,21 +68,19 @@ static const int priorities[] =
+ LOG_DEBUG
+ };
+
+-enum
+- {
+- ident_length = 64,
+- msg_length = 64
+- };
++#define IDENT_LENGTH 64
++#define MSG_LENGTH 1024
+
+ #define SYSLOG_MSG_BASE "syslog_message"
+ #define OPENLOG_IDENT "openlog_ident"
++static char large_message[MSG_LENGTH];
+
+ struct msg_t
+ {
+ int priority;
+ int facility;
+- char ident[ident_length];
+- char msg[msg_length];
++ char ident[IDENT_LENGTH];
++ char msg[MSG_LENGTH];
+ pid_t pid;
+ };
+
+@@ -147,6 +145,37 @@ check_syslog_message (const struct msg_t *msg, int msgnum, int options,
+ return true;
+ }
+
++static void
++send_syslog_large (int options)
++{
++ int facility = LOG_USER;
++ int priority = LOG_INFO;
++
++ syslog (facility | priority, "%s %d %d", large_message, facility,
++ priority);
++}
++
++static void
++send_vsyslog_large (int options)
++{
++ int facility = LOG_USER;
++ int priority = LOG_INFO;
++
++ call_vsyslog (facility | priority, "%s %d %d", large_message, facility,
++ priority);
++}
++
++static bool
++check_syslog_message_large (const struct msg_t *msg, int msgnum, int options,
++ pid_t pid)
++{
++ TEST_COMPARE (msg->facility, LOG_USER);
++ TEST_COMPARE (msg->priority, LOG_INFO);
++ TEST_COMPARE_STRING (msg->msg, large_message);
++
++ return false;
++}
++
+ static void
+ send_openlog (int options)
+ {
+@@ -179,6 +208,17 @@ send_openlog (int options)
+ closelog ();
+ }
+
++static void
++send_openlog_large (int options)
++{
++ /* Define a non-default IDENT and a not default facility. */
++ openlog (OPENLOG_IDENT, options, LOG_LOCAL0);
++
++ syslog (LOG_INFO, "%s %d %d", large_message, LOG_LOCAL0, LOG_INFO);
++
++ closelog ();
++}
++
+ static bool
+ check_openlog_message (const struct msg_t *msg, int msgnum,
+ int options, pid_t pid)
+@@ -189,7 +229,7 @@ check_openlog_message (const struct msg_t *msg, int msgnum,
+ int expected_priority = priorities[msgnum % array_length (priorities)];
+ TEST_COMPARE (msg->priority, expected_priority);
+
+- char expected_ident[ident_length];
++ char expected_ident[IDENT_LENGTH];
+ snprintf (expected_ident, sizeof (expected_ident), "%s%s%.0d%s:",
+ OPENLOG_IDENT,
+ options & LOG_PID ? "[" : "",
+@@ -211,15 +251,38 @@ check_openlog_message (const struct msg_t *msg, int msgnum,
+ return true;
+ }
+
++static bool
++check_openlog_message_large (const struct msg_t *msg, int msgnum,
++ int options, pid_t pid)
++{
++ char expected_ident[IDENT_LENGTH];
++ snprintf (expected_ident, sizeof (expected_ident), "%s%s%.0d%s:",
++ OPENLOG_IDENT,
++ options & LOG_PID ? "[" : "",
++ options & LOG_PID ? pid : 0,
++ options & LOG_PID ? "]" : "");
++
++ TEST_COMPARE_STRING (msg->ident, expected_ident);
++ TEST_COMPARE_STRING (msg->msg, large_message);
++ TEST_COMPARE (msg->priority, LOG_INFO);
++ TEST_COMPARE (msg->facility, LOG_LOCAL0);
++
++ return false;
++}
++
+ static struct msg_t
+ parse_syslog_msg (const char *msg)
+ {
+ struct msg_t r = { .pid = -1 };
+ int number;
+
++#define STRINPUT(size) XSTRINPUT(size)
++#define XSTRINPUT(size) "%" # size "s"
++
+ /* The message in the form:
+- <179>Apr 8 14:51:19 tst-syslog: syslog message 176 3 */
+- int n = sscanf (msg, "<%3d>%*s %*d %*d:%*d:%*d %32s %64s %*d %*d",
++ <179>Apr 8 14:51:19 tst-syslog: message 176 3 */
++ int n = sscanf (msg, "<%3d>%*s %*d %*d:%*d:%*d " STRINPUT(IDENT_LENGTH)
++ " " STRINPUT(MSG_LENGTH) " %*d %*d",
+ &number, r.ident, r.msg);
+ TEST_COMPARE (n, 3);
+
+@@ -246,7 +309,7 @@ parse_syslog_console (const char *msg)
+
+ /* The message in the form:
+ openlog_ident: syslog_message 128 0 */
+- int n = sscanf (msg, "%32s %64s %d %d",
++ int n = sscanf (msg, STRINPUT(IDENT_LENGTH) " " STRINPUT(MSG_LENGTH) " %d %d",
+ r.ident, r.msg, &facility, &priority);
+ TEST_COMPARE (n, 4);
+
+@@ -281,7 +344,7 @@ check_syslog_udp (void (*syslog_send)(int), int options,
+ int msgnum = 0;
+ while (1)
+ {
+- char buf[512];
++ char buf[2048];
+ size_t l = xrecvfrom (server_udp, buf, sizeof (buf), 0,
+ (struct sockaddr *) &addr, &addrlen);
+ buf[l] = '\0';
+@@ -325,7 +388,7 @@ check_syslog_tcp (void (*syslog_send)(int), int options,
+
+ int client_tcp = xaccept (server_tcp, NULL, NULL);
+
+- char buf[512], *rb = buf;
++ char buf[2048], *rb = buf;
+ size_t rbl = sizeof (buf);
+ size_t prl = 0; /* Track the size of the partial record. */
+ int msgnum = 0;
+@@ -393,20 +456,34 @@ check_syslog_console_read (FILE *fp)
+ }
+
+ static void
+-check_syslog_console (void)
++check_syslog_console_read_large (FILE *fp)
++{
++ char buf[2048];
++ TEST_VERIFY (fgets (buf, sizeof (buf), fp) != NULL);
++ struct msg_t msg = parse_syslog_console (buf);
++
++ TEST_COMPARE_STRING (msg.ident, OPENLOG_IDENT ":");
++ TEST_COMPARE_STRING (msg.msg, large_message);
++ TEST_COMPARE (msg.priority, LOG_INFO);
++ TEST_COMPARE (msg.facility, LOG_LOCAL0);
++}
++
++static void
++check_syslog_console (void (*syslog_send)(int),
++ void (*syslog_check)(FILE *fp))
+ {
+ xmkfifo (_PATH_CONSOLE, 0666);
+
+ pid_t sender_pid = xfork ();
+ if (sender_pid == 0)
+ {
+- send_openlog (LOG_CONS);
++ syslog_send (LOG_CONS);
+ _exit (0);
+ }
+
+ {
+ FILE *fp = xfopen (_PATH_CONSOLE, "r+");
+- check_syslog_console_read (fp);
++ syslog_check (fp);
+ xfclose (fp);
+ }
+
+@@ -425,16 +502,28 @@ send_openlog_callback (void *clousure)
+ }
+
+ static void
+-check_syslog_perror (void)
++send_openlog_callback_large (void *clousure)
++{
++ int options = *(int *) clousure;
++ send_openlog_large (options);
++}
++
++static void
++check_syslog_perror (bool large)
+ {
+ struct support_capture_subprocess result;
+- result = support_capture_subprocess (send_openlog_callback,
++ result = support_capture_subprocess (large
++ ? send_openlog_callback_large
++ : send_openlog_callback,
+ &(int){LOG_PERROR});
+
+ FILE *mfp = fmemopen (result.err.buffer, result.err.length, "r");
+ if (mfp == NULL)
+ FAIL_EXIT1 ("fmemopen: %m");
+- check_syslog_console_read (mfp);
++ if (large)
++ check_syslog_console_read_large (mfp);
++ else
++ check_syslog_console_read (mfp);
+ xfclose (mfp);
+
+ support_capture_subprocess_check (&result, "tst-openlog-child", 0,
+@@ -462,10 +551,31 @@ do_test (void)
+ check_syslog_tcp (send_openlog, LOG_PID, check_openlog_message);
+
+ /* Check the LOG_CONS option. */
+- check_syslog_console ();
++ check_syslog_console (send_openlog, check_syslog_console_read);
+
+ /* Check the LOG_PERROR option. */
+- check_syslog_perror ();
++ check_syslog_perror (false);
++
++ /* Similar tests as before, but with a large message to trigger the
++ syslog path that uses dynamically allocated memory. */
++ memset (large_message, 'a', sizeof large_message - 1);
++ large_message[sizeof large_message - 1] = '\0';
++
++ check_syslog_udp (send_syslog_large, 0, check_syslog_message_large);
++ check_syslog_tcp (send_syslog_large, 0, check_syslog_message_large);
++
++ check_syslog_udp (send_vsyslog_large, 0, check_syslog_message_large);
++ check_syslog_tcp (send_vsyslog_large, 0, check_syslog_message_large);
++
++ check_syslog_udp (send_openlog_large, 0, check_openlog_message_large);
++ check_syslog_tcp (send_openlog_large, 0, check_openlog_message_large);
++
++ check_syslog_udp (send_openlog_large, LOG_PID, check_openlog_message_large);
++ check_syslog_tcp (send_openlog_large, LOG_PID, check_openlog_message_large);
++
++ check_syslog_console (send_openlog_large, check_syslog_console_read_large);
++
++ check_syslog_perror (true);
+
+ return 0;
+ }
+--
+2.30.2
+
diff --git a/src/patches/glibc-2.36-syslog-whitespace-fix.patch b/src/patches/glibc-2.36-syslog-whitespace-fix.patch
new file mode 100644
index 000000000..0e80cea7f
--- /dev/null
+++ b/src/patches/glibc-2.36-syslog-whitespace-fix.patch
@@ -0,0 +1,58 @@
+From 645d94808aaa90fb1b20a25ff70bb50d9eb1d55b Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella(a)linaro.org>
+Date: Mon, 5 Sep 2022 09:34:39 -0300
+Subject: [PATCH] syslog: Remove extra whitespace between timestamp and message
+ (BZ#29544)
+
+The rfc3164 clear states that a single space character must follow
+the timestamp field.
+
+Checked on x86_64-linux-gnu.
+---
+ misc/syslog.c | 2 +-
+ misc/tst-syslog.c | 9 ++++++---
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/misc/syslog.c b/misc/syslog.c
+index b88f66c835..f67d4b58a4 100644
+--- a/misc/syslog.c
++++ b/misc/syslog.c
+@@ -167,7 +167,7 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
+ _nl_C_locobj_ptr);
+
+ #define SYSLOG_HEADER(__pri, __timestamp, __msgoff, pid) \
+- "<%d>%s %n%s%s%.0d%s: ", \
++ "<%d>%s%n%s%s%.0d%s: ", \
+ __pri, __timestamp, __msgoff, \
+ LogTag == NULL ? __progname : LogTag, \
+ "[" + (pid == 0), pid, "]" + (pid == 0)
+diff --git a/misc/tst-syslog.c b/misc/tst-syslog.c
+index 1d332ece53..3560b518a2 100644
+--- a/misc/tst-syslog.c
++++ b/misc/tst-syslog.c
+@@ -275,16 +275,19 @@ parse_syslog_msg (const char *msg)
+ {
+ struct msg_t r = { .pid = -1 };
+ int number;
++ int wsb, wsa;
+
+ #define STRINPUT(size) XSTRINPUT(size)
+ #define XSTRINPUT(size) "%" # size "s"
+
+ /* The message in the form:
+- <179>Apr 8 14:51:19 tst-syslog: message 176 3 */
+- int n = sscanf (msg, "<%3d>%*s %*d %*d:%*d:%*d " STRINPUT(IDENT_LENGTH)
++ <179>Apr 8 14:51:19 tst-syslog: message 176 3 */
++ int n = sscanf (msg, "<%3d>%*s %*d %*d:%*d:%*d%n %n" STRINPUT(IDENT_LENGTH)
+ " " STRINPUT(MSG_LENGTH) " %*d %*d",
+- &number, r.ident, r.msg);
++ &number, &wsb, &wsa, r.ident, r.msg);
+ TEST_COMPARE (n, 3);
++ /* It should only one space between timestamp and message. */
++ TEST_COMPARE (wsa - wsb, 1);
+
+ r.facility = number & LOG_FACMASK;
+ r.priority = number & LOG_PRIMASK;
+--
+2.30.2
+
--
2.30.2