glibc: Fix added whitespace in syslog messages

Message ID 20221007162415.102723-1-michael.tremer@ipfire.org
State Accepted
Commit 692d18285f59f78cfea96b5e2d9f21bed01360ba
Headers
Series glibc: Fix added whitespace in syslog messages |

Commit Message

Michael Tremer Oct. 7, 2022, 4:24 p.m. UTC
  Fixes: #12949
Signed-off-by: Michael Tremer <michael.tremer@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
  

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@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@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@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
+