diff options
author | Arjun Shankar <arjun@redhat.com> | 2024-01-15 17:44:44 +0100 |
---|---|---|
committer | Andreas K. Hüttel <dilfridge@gentoo.org> | 2024-01-31 17:25:55 +0100 |
commit | 5a1f6468d93594d372237be4c8dc2c2f682323be (patch) | |
tree | 6c5cf73fd46ae6ffb419c0504353f56fe0873da3 | |
parent | syslog: Fix heap buffer overflow in __vsyslog_internal (CVE-2023-6246) (diff) | |
download | glibc-5a1f6468d93594d372237be4c8dc2c2f682323be.tar.gz glibc-5a1f6468d93594d372237be4c8dc2c2f682323be.tar.bz2 glibc-5a1f6468d93594d372237be4c8dc2c2f682323be.zip |
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)
(cherry picked from commit 67062eccd9a65d7fda9976a56aeaaf6c25a80214)
-rw-r--r-- | misc/syslog.c | 39 |
1 files 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; } } |