1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-12-24 17:51:17 +03:00

syslog: Fix heap buffer overflow in __vsyslog_internal (CVE-2023-6246)

__vsyslog_internal did not handle a case where printing a SYSLOG_HEADER
containing a long program name failed to update the required buffer
size, leading to the allocation and overflow of a too-small buffer on
the heap.  This commit fixes that.  It also adds a new regression test
that uses glibc.malloc.check.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
Arjun Shankar
2024-01-15 17:44:43 +01:00
parent 8aeec0eb5a
commit 6bd0e4efcc
4 changed files with 84 additions and 17 deletions

View File

@@ -124,8 +124,9 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
{
/* Try to use a static buffer as an optimization. */
char bufs[1024];
char *buf = NULL;
size_t bufsize = 0;
char *buf = bufs;
size_t bufsize;
int msgoff;
int saved_errno = errno;
@@ -177,29 +178,50 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
#define SYSLOG_HEADER_WITHOUT_TS(__pri, __msgoff) \
"<%d>: %n", __pri, __msgoff
int l;
int l, vl;
if (has_ts)
l = __snprintf (bufs, sizeof bufs,
SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
else
l = __snprintf (bufs, sizeof bufs,
SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
char *pos;
size_t len;
if (0 <= l && l < sizeof bufs)
{
va_list apc;
va_copy (apc, ap);
/* Restore errno for %m format. */
__set_errno (saved_errno);
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;
va_end (apc);
/* At this point, there is still a chance that we can print the
remaining part of the log into bufs and use that. */
pos = bufs + l;
len = sizeof (bufs) - l;
}
else
{
buf = NULL;
/* We already know that bufs is too small to use for this log message.
The next vsnprintf into bufs is used only to calculate the total
required buffer length. We will discard bufs contents and allocate
an appropriately sized buffer later instead. */
pos = bufs;
len = sizeof (bufs);
}
{
va_list apc;
va_copy (apc, ap);
/* Restore errno for %m format. */
__set_errno (saved_errno);
vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
if (!(0 <= vl && vl < len))
buf = NULL;
bufsize = l + vl;
va_end (apc);
}
if (buf == NULL)
{