106 lines
3.1 KiB
Diff
106 lines
3.1 KiB
Diff
From 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 Mon Sep 17 00:00:00 2001
|
|
From: Arjun Shankar <arjun@redhat.com>
|
|
Date: Mon, 15 Jan 2024 17:44:44 +0100
|
|
Subject: [PATCH] syslog: Fix heap buffer overflow in __vsyslog_internal
|
|
(CVE-2023-6779)
|
|
|
|
__vsyslog_internal used the return value of snprintf/vsnprintf to
|
|
calculate buffer sizes for memory allocation. If these functions (for
|
|
any reason) failed and returned -1, the resulting buffer would be too
|
|
small to hold output. This commit fixes that.
|
|
|
|
All snprintf/vsnprintf calls are checked for negative return values and
|
|
the function silently returns upon encountering them.
|
|
|
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
(cherry picked from commit 7e5a0c286da33159d47d0122007aac016f3e02cd)
|
|
---
|
|
misc/syslog.c | 39 ++++++++++++++++++++++++++++-----------
|
|
1 file changed, 28 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/misc/syslog.c b/misc/syslog.c
|
|
index fe1daf988b..3108ae9134 100644
|
|
--- a/misc/syslog.c
|
|
+++ b/misc/syslog.c
|
|
@@ -183,11 +183,13 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
|
|
else
|
|
l = __snprintf (bufs, sizeof bufs,
|
|
SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
|
|
+ if (l < 0)
|
|
+ goto out;
|
|
|
|
char *pos;
|
|
size_t len;
|
|
|
|
- if (0 <= l && l < sizeof bufs)
|
|
+ if (l < sizeof bufs)
|
|
{
|
|
/* At this point, there is still a chance that we can print the
|
|
remaining part of the log into bufs and use that. */
|
|
@@ -213,12 +215,15 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
|
|
__set_errno (saved_errno);
|
|
|
|
vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
|
|
+ va_end (apc);
|
|
+
|
|
+ if (vl < 0)
|
|
+ goto out;
|
|
|
|
- if (!(0 <= vl && vl < len))
|
|
+ if (vl >= len)
|
|
buf = NULL;
|
|
|
|
bufsize = l + vl;
|
|
- va_end (apc);
|
|
}
|
|
|
|
if (buf == NULL)
|
|
@@ -229,25 +234,37 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
|
|
/* Tell the cancellation handler to free this buffer. */
|
|
clarg.buf = buf;
|
|
|
|
+ int cl;
|
|
if (has_ts)
|
|
- __snprintf (buf, l + 1,
|
|
- SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
|
|
+ cl = __snprintf (buf, l + 1,
|
|
+ SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
|
|
else
|
|
- __snprintf (buf, l + 1,
|
|
- SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
|
|
+ cl = __snprintf (buf, l + 1,
|
|
+ SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
|
|
+ if (cl != l)
|
|
+ goto out;
|
|
|
|
va_list apc;
|
|
va_copy (apc, ap);
|
|
- __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
|
|
- mode_flags);
|
|
+ cl = __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
|
|
+ mode_flags);
|
|
va_end (apc);
|
|
+
|
|
+ if (cl != vl)
|
|
+ goto out;
|
|
}
|
|
else
|
|
{
|
|
+ int bl;
|
|
/* Nothing much to do but emit an error message. */
|
|
- bufsize = __snprintf (bufs, sizeof bufs,
|
|
- "out of memory[%d]", __getpid ());
|
|
+ bl = __snprintf (bufs, sizeof bufs,
|
|
+ "out of memory[%d]", __getpid ());
|
|
+ if (bl < 0 || bl >= sizeof bufs)
|
|
+ goto out;
|
|
+
|
|
+ bufsize = bl;
|
|
buf = bufs;
|
|
+ msgoff = 0;
|
|
}
|
|
}
|
|
|
|
--
|
|
2.39.3
|
|
|