1 From 23514c72b780f3da097ecf33a793b7ba9c2070d2 Mon Sep 17 00:00:00 2001
2 From: Arjun Shankar <arjun@redhat.com>
3 Date: Mon, 15 Jan 2024 17:44:43 +0100
4 Subject: [PATCH 42/44] syslog: Fix heap buffer overflow in __vsyslog_internal
7 __vsyslog_internal did not handle a case where printing a SYSLOG_HEADER
8 containing a long program name failed to update the required buffer
9 size, leading to the allocation and overflow of a too-small buffer on
10 the heap. This commit fixes that. It also adds a new regression test
11 that uses glibc.malloc.check.
13 Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
14 Reviewed-by: Carlos O'Donell <carlos@redhat.com>
15 Tested-by: Carlos O'Donell <carlos@redhat.com>
16 (cherry picked from commit 6bd0e4efcc78f3c0115e5ea9739a1642807450da)
19 misc/syslog.c | 50 +++++++++++++------
20 misc/tst-syslog-long-progname.c | 39 +++++++++++++++
22 4 files changed, 82 insertions(+), 15 deletions(-)
23 create mode 100644 misc/tst-syslog-long-progname.c
24 create mode 100644 misc/tst-syslog-long-progname.root/postclean.req
26 diff --git a/misc/Makefile b/misc/Makefile
27 index fe0d49c1de..90b31952c5 100644
30 @@ -289,7 +289,10 @@ tests-special += $(objpfx)tst-error1-mem.out \
31 $(objpfx)tst-allocate_once-mem.out
34 -tests-container := tst-syslog
37 + tst-syslog-long-progname \
40 CFLAGS-select.c += -fexceptions -fasynchronous-unwind-tables
41 CFLAGS-tsearch.c += $(uses-callbacks)
42 @@ -351,6 +354,9 @@ $(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out
43 $(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \
46 +tst-syslog-long-progname-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \
47 + LD_PRELOAD=libc_malloc_debug.so.0
49 $(objpfx)tst-select: $(librt)
50 $(objpfx)tst-select-time64: $(librt)
51 $(objpfx)tst-pselect: $(librt)
52 diff --git a/misc/syslog.c b/misc/syslog.c
53 index 1b8cb722c5..814d224a1e 100644
56 @@ -124,8 +124,9 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
58 /* Try to use a static buffer as an optimization. */
66 int saved_errno = errno;
68 @@ -177,29 +178,50 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
69 #define SYSLOG_HEADER_WITHOUT_TS(__pri, __msgoff) \
70 "<%d>: %n", __pri, __msgoff
75 l = __snprintf (bufs, sizeof bufs,
76 SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
78 l = __snprintf (bufs, sizeof bufs,
79 SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
84 if (0 <= l && l < sizeof bufs)
88 + /* At this point, there is still a chance that we can print the
89 + remaining part of the log into bufs and use that. */
91 + len = sizeof (bufs) - l;
96 + /* We already know that bufs is too small to use for this log message.
97 + The next vsnprintf into bufs is used only to calculate the total
98 + required buffer length. We will discard bufs contents and allocate
99 + an appropriately sized buffer later instead. */
101 + len = sizeof (bufs);
104 - /* Restore errno for %m format. */
105 - __set_errno (saved_errno);
110 - int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
112 - if (0 <= vl && vl < sizeof bufs - l)
115 + /* Restore errno for %m format. */
116 + __set_errno (saved_errno);
120 + vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
122 + if (!(0 <= vl && vl < len))
131 diff --git a/misc/tst-syslog-long-progname.c b/misc/tst-syslog-long-progname.c
133 index 0000000000..88f37a8a00
135 +++ b/misc/tst-syslog-long-progname.c
137 +/* Test heap buffer overflow in syslog with long __progname (CVE-2023-6246)
138 + Copyright (C) 2023 Free Software Foundation, Inc.
139 + This file is part of the GNU C Library.
141 + The GNU C Library is free software; you can redistribute it and/or
142 + modify it under the terms of the GNU Lesser General Public
143 + License as published by the Free Software Foundation; either
144 + version 2.1 of the License, or (at your option) any later version.
146 + The GNU C Library is distributed in the hope that it will be useful,
147 + but WITHOUT ANY WARRANTY; without even the implied warranty of
148 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
149 + Lesser General Public License for more details.
151 + You should have received a copy of the GNU Lesser General Public
152 + License along with the GNU C Library; if not, see
153 + <https://www.gnu.org/licenses/>. */
158 +extern char * __progname;
163 + char long_progname[2048];
165 + memset (long_progname, 'X', sizeof (long_progname) - 1);
166 + long_progname[sizeof (long_progname) - 1] = '\0';
168 + __progname = long_progname;
170 + syslog (LOG_INFO, "Hello, World!");
175 +#include <support/test-driver.c>
176 diff --git a/misc/tst-syslog-long-progname.root/postclean.req b/misc/tst-syslog-long-progname.root/postclean.req
178 index 0000000000..e69de29bb2