From 40901382721a7eae384d9217e9e1f884bdbd6cf1b846f781a53057fddd275872 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Wed, 7 Sep 2022 07:38:45 +0000 Subject: [PATCH] Accepting request 1001591 from home:Andreas_Schwab:Factory - syslog-large-messages.patch: syslog: Fix large messages (CVE-2022-39046, bsc#1203011, BZ #29536) - dlmopen-libc-early-init.patch: elf: Call __libc_early_init for reused namespaces (BZ #29528) - ldd-vdso-dependency.patch: elf: Restore how vDSO dependency is printed with LD_TRACE_LOADED_OBJECTS (BZ #29539) - syslog-extra-whitespace.patch: syslog: Remove extra whitespace between timestamp and message (BZ #29544) OBS-URL: https://build.opensuse.org/request/show/1001591 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=628 --- dlmopen-libc-early-init.patch | 239 ++++++++++++++++++++++++ glibc.changes | 12 ++ glibc.spec | 12 ++ ldd-vdso-dependency.patch | 50 +++++ syslog-extra-whitespace.patch | 58 ++++++ syslog-large-messages.patch | 336 ++++++++++++++++++++++++++++++++++ 6 files changed, 707 insertions(+) create mode 100644 dlmopen-libc-early-init.patch create mode 100644 ldd-vdso-dependency.patch create mode 100644 syslog-extra-whitespace.patch create mode 100644 syslog-large-messages.patch diff --git a/dlmopen-libc-early-init.patch b/dlmopen-libc-early-init.patch new file mode 100644 index 0000000..65e7611 --- /dev/null +++ b/dlmopen-libc-early-init.patch @@ -0,0 +1,239 @@ +From 924e4f3eaa502ce82fccf8537f021a796d158771 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 26 Aug 2022 21:15:43 +0200 +Subject: [PATCH] elf: Call __libc_early_init for reused namespaces (bug 29528) + +libc_map is never reset to NULL, neither during dlclose nor on a +dlopen call which reuses the namespace structure. As a result, if a +namespace is reused, its libc is not initialized properly. The most +visible result is a crash in the functions. + +To prevent similar bugs on namespace reuse from surfacing, +unconditionally initialize the chosen namespace to zero using memset. + +(cherry picked from commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe) +--- + NEWS | 1 + + elf/Makefile | 25 ++++++++++++++++++ + elf/dl-open.c | 13 ++++++---- + elf/tst-dlmopen-twice-mod1.c | 37 ++++++++++++++++++++++++++ + elf/tst-dlmopen-twice-mod2.c | 50 ++++++++++++++++++++++++++++++++++++ + elf/tst-dlmopen-twice.c | 34 ++++++++++++++++++++++++ + 6 files changed, 155 insertions(+), 5 deletions(-) + create mode 100644 elf/tst-dlmopen-twice-mod1.c + create mode 100644 elf/tst-dlmopen-twice-mod2.c + create mode 100644 elf/tst-dlmopen-twice.c + +diff --git a/elf/Makefile b/elf/Makefile +index fd77d0c7c8..43353a4b08 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -408,6 +408,7 @@ tests += \ + tst-dlmopen4 \ + tst-dlmopen-dlerror \ + tst-dlmopen-gethostbyname \ ++ tst-dlmopen-twice \ + tst-dlopenfail \ + tst-dlopenfail-2 \ + tst-dlopenrpath \ +@@ -834,6 +835,8 @@ modules-names += \ + tst-dlmopen1mod \ + tst-dlmopen-dlerror-mod \ + tst-dlmopen-gethostbyname-mod \ ++ tst-dlmopen-twice-mod1 \ ++ tst-dlmopen-twice-mod2 \ + tst-dlopenfaillinkmod \ + tst-dlopenfailmod1 \ + tst-dlopenfailmod2 \ +@@ -2967,3 +2970,25 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \ + grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \ + && grep -q '^status: 127$$' $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \ ++ $(objpfx)tst-audit-tlsdesc-mod2.so \ ++ $(shared-thread-library) ++ifeq (yes,$(have-mtls-dialect-gnu2)) ++# The test is valid for all TLS types, but we want to exercise GNU2 ++# TLS if possible. ++CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2 ++CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2 ++endif ++$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library) ++$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \ ++ $(objpfx)tst-audit-tlsdesc-mod2.so ++$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so ++$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so ++tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so ++$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so ++tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so ++ ++$(objpfx)tst-dlmopen-twice.out: \ ++ $(objpfx)tst-dlmopen-twice-mod1.so \ ++ $(objpfx)tst-dlmopen-twice-mod2.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index a23e65926b..46e8066fd8 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -844,11 +844,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, + _dl_signal_error (EINVAL, file, NULL, N_("\ + no more namespaces available for dlmopen()")); + } +- else if (nsid == GL(dl_nns)) +- { +- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); +- ++GL(dl_nns); +- } ++ ++ if (nsid == GL(dl_nns)) ++ ++GL(dl_nns); ++ ++ /* Initialize the new namespace. Most members are ++ zero-initialized, only the lock needs special treatment. */ ++ memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid])); ++ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); + + _dl_debug_update (nsid)->r_state = RT_CONSISTENT; + } +diff --git a/elf/tst-dlmopen-twice-mod1.c b/elf/tst-dlmopen-twice-mod1.c +new file mode 100644 +index 0000000000..0eaf04948c +--- /dev/null ++++ b/elf/tst-dlmopen-twice-mod1.c +@@ -0,0 +1,37 @@ ++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod1.so loaded"); ++ fflush (stdout); ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded"); ++ fflush (stdout); ++} ++ ++/* Large allocation. The second module does not have this, so it ++ should load libc at a different address. */ ++char large_allocate[16 * 1024 * 1024]; +diff --git a/elf/tst-dlmopen-twice-mod2.c b/elf/tst-dlmopen-twice-mod2.c +new file mode 100644 +index 0000000000..40c6c01f96 +--- /dev/null ++++ b/elf/tst-dlmopen-twice-mod2.c +@@ -0,0 +1,50 @@ ++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod2.so loaded"); ++ fflush (stdout); ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded"); ++ fflush (stdout); ++} ++ ++int ++run_check (void) ++{ ++ puts ("info: about to call isalpha"); ++ fflush (stdout); ++ ++ volatile char ch = 'a'; ++ if (!isalpha (ch)) ++ { ++ puts ("error: isalpha ('a') is not true"); ++ fflush (stdout); ++ return 1; ++ } ++ return 0; ++} +diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c +new file mode 100644 +index 0000000000..449f3c8fa9 +--- /dev/null ++++ b/elf/tst-dlmopen-twice.c +@@ -0,0 +1,34 @@ ++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW); ++ xdlclose (handle); ++ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW); ++ int (*run_check) (void) = xdlsym (handle, "run_check"); ++ TEST_COMPARE (run_check (), 0); ++ xdlclose (handle); ++ return 0; ++} ++ ++#include +-- +2.37.3 + diff --git a/glibc.changes b/glibc.changes index 169fd86..88e9e97 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Tue Sep 6 11:22:46 UTC 2022 - Andreas Schwab + +- syslog-large-messages.patch: syslog: Fix large messages (CVE-2022-39046, + bsc#1203011, BZ #29536) +- dlmopen-libc-early-init.patch: elf: Call __libc_early_init for reused + namespaces (BZ #29528) +- ldd-vdso-dependency.patch: elf: Restore how vDSO dependency is printed + with LD_TRACE_LOADED_OBJECTS (BZ #29539) +- syslog-extra-whitespace.patch: syslog: Remove extra whitespace between + timestamp and message (BZ #29544) + ------------------------------------------------------------------- Wed Aug 24 09:29:02 UTC 2022 - Fabian Vogt diff --git a/glibc.spec b/glibc.spec index feb29d0..528f533 100644 --- a/glibc.spec +++ b/glibc.spec @@ -287,6 +287,14 @@ Patch1001: sys-mount-kernel-definition.patch Patch1002: sys-mount-usage.patch # PATCH-FIX-UPSTREAM nscd: Fix netlink cache invalidation if epoll is used (BZ #29415) Patch1003: nscd-netlink-cache-invalidation.patch +# PATCH-FIX-UPSTREAM syslog: Fix large messages (CVE-2022-39046, BZ #29536) +Patch1004: syslog-large-messages.patch +# PATCH-FIX-UPSTREAM elf: Call __libc_early_init for reused namespaces (BZ #29528) +Patch1005: dlmopen-libc-early-init.patch +# PATCH-FIX-UPSTREAM elf: Restore how vDSO dependency is printed with LD_TRACE_LOADED_OBJECTS (BZ #29539) +Patch1006: ldd-vdso-dependency.patch +# PATCH-FIX-UPSTREAM syslog: Remove extra whitespace between timestamp and message (BZ #29544) +Patch1007: syslog-extra-whitespace.patch ### # Patches awaiting upstream approval @@ -515,6 +523,10 @@ library in a cross compilation setting. %patch1001 -p1 %patch1002 -p1 %patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 +%patch1006 -p1 +%patch1007 -p1 %endif %patch2000 -p1 diff --git a/ldd-vdso-dependency.patch b/ldd-vdso-dependency.patch new file mode 100644 index 0000000..bd6197c --- /dev/null +++ b/ldd-vdso-dependency.patch @@ -0,0 +1,50 @@ +From b3736d1a3c60a3ec9959bf3b38794958546bf6a2 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 30 Aug 2022 13:35:52 -0300 +Subject: [PATCH] elf: Restore how vDSO dependency is printed with + LD_TRACE_LOADED_OBJECTS (BZ #29539) + +The d7703d3176d225d5743b21811d888619eba39e82 changed how vDSO like +dependencies are printed, instead of just the name and address it +follows other libraries mode and prints 'name => path'. + +Unfortunately, this broke some ldd consumer that uses the output to +filter out the program's dependencies. For instance CMake +bundleutilities module [1], where GetPrequirite uses the regex to filter +out 'name => path' [2]. + +This patch restore the previous way to print just the name and the +mapping address. + +Checked on x86_64-linux-gnu. + +[1] https://github.com/Kitware/CMake/tree/master/Tests/BundleUtilities +[2] https://github.com/Kitware/CMake/blob/master/Modules/GetPrerequisites.cmake#L733 + +Reviewed-by: Florian Weimer +(cherry picked from commit 1e903124cec4492463d075c6c061a2a772db77bf) +--- + NEWS | 2 +- + elf/rtld.c | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/elf/rtld.c b/elf/rtld.c +index cbbaf4a331..3e771a93d8 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2122,6 +2122,12 @@ dl_main (const ElfW(Phdr) *phdr, + if (l->l_faked) + /* The library was not found. */ + _dl_printf ("\t%s => not found\n", l->l_libname->name); ++ else if (strcmp (l->l_libname->name, l->l_name) == 0) ++ /* Print vDSO like libraries without duplicate name. Some ++ consumers depend of this format. */ ++ _dl_printf ("\t%s (0x%0*Zx)\n", l->l_libname->name, ++ (int) sizeof l->l_map_start * 2, ++ (size_t) l->l_map_start); + else + _dl_printf ("\t%s => %s (0x%0*Zx)\n", + DSO_FILENAME (l->l_libname->name), +-- +2.37.3 + diff --git a/syslog-extra-whitespace.patch b/syslog-extra-whitespace.patch new file mode 100644 index 0000000..7542f68 --- /dev/null +++ b/syslog-extra-whitespace.patch @@ -0,0 +1,58 @@ +From 645d94808aaa90fb1b20a25ff70bb50d9eb1d55b Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +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.37.3 + diff --git a/syslog-large-messages.patch b/syslog-large-messages.patch new file mode 100644 index 0000000..4db9617 --- /dev/null +++ b/syslog-large-messages.patch @@ -0,0 +1,336 @@ +From b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +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 +(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.37.3 +