[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#991731: unblock: fetchmail/6.4.16-4



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Hi RMs,

I would like to ask for unblocking fetchmail, fixing a security issue.

[ Reason ]
When logging long messages, fetchmail might segfault or leak
information to logs.

[ Impact ]
Normal logging in all cases.

[ Tests ]
Local tests.

[ Risks ]
None.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

unblock fetchmail/6.4.16-4

Thanks for considering,
Laszlo/GCS
diff -Nru fetchmail-6.4.16/debian/changelog fetchmail-6.4.16/debian/changelog
--- fetchmail-6.4.16/debian/changelog	2021-06-26 23:53:00.000000000 +0200
+++ fetchmail-6.4.16/debian/changelog	2021-07-29 00:18:56.000000000 +0200
@@ -1,3 +1,10 @@
+fetchmail (6.4.16-4) unstable; urgency=high
+
+  * Backport upstream security fix for CVE-2021-36386: denial of service or
+    information disclosure when logging long messages.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.org>  Thu, 29 Jul 2021 00:18:56 +0200
+
 fetchmail (6.4.16-3) unstable; urgency=medium
 
   * Fix operation autopkgtest.
diff -Nru fetchmail-6.4.16/debian/patches/11_fix_CVE-2021-38386.patch fetchmail-6.4.16/debian/patches/11_fix_CVE-2021-38386.patch
--- fetchmail-6.4.16/debian/patches/11_fix_CVE-2021-38386.patch	1970-01-01 01:00:00.000000000 +0100
+++ fetchmail-6.4.16/debian/patches/11_fix_CVE-2021-38386.patch	2021-07-29 00:18:56.000000000 +0200
@@ -0,0 +1,258 @@
+From c546c8299243a10a7b85c638e0e61396ecd5d8b5 Mon Sep 17 00:00:00 2001
+From: Matthias Andree <matthias.andree@gmx.de>
+Date: Wed, 7 Jul 2021 16:22:57 +0200
+Subject: [PATCH] Fix SIGSEGV when resizing report*() buffer.
+
+Reported (with a different patch suggestion) by
+Christian Herdtweck <christian.herdtweck@intra2net.com>.
+
+Note that vsnprintf() calls va_arg(), and depending on operating system,
+compiler, configuration, this will invalidate the va_list argument
+pointer, so that va_start has to be called again before a subsequent
+vsnprintf(). However, it is better to do away with the loop and the
+trial-and-error, and leverage the return value of vsnprintf instead for
+a direct one-off resizing, whilst taking into account that on SUSv2
+systems, the return value can be useless if the size argument to
+vsnprintf is 0.
+---
+ NEWS     |  18 ++++++++
+ report.c | 138 +++++++++++++++++++++++++++++++------------------------
+ 2 files changed, 95 insertions(+), 61 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 04239b16..67dc1f9e 100644
+--- a/NEWS
++++ b/NEWS
+@@ -64,6 +64,24 @@ removed from a 6.5.0 or newer release.)
+   for end-of-life OpenSSL versions may be removed even from patchlevel releases.
+ 
+ --------------------------------------------------------------------------------
++fetchmail-6.4.20 (not yet released):
++
++# SECURITY FIX:
++* When a log message exceeds c. 2 kByte in size, for instance, with very long 
++  header contents, and depending on verbosity option, fetchmail can crash or
++  misreport each first log message that requires a buffer reallocation.
++  fetchmail then reallocates memory and re-runs vsnprintf() without another 
++  call to va_start(), so it reads garbage. The exact impact depends on 
++  many factors around the compiler and operating system configurations used and 
++  the implementation details of the stdarg.h interfaces of the two functions
++  mentioned before. To fix CVE-2021-38386.
++
++  Reported by Christian Herdtweck of Intra2net AG, Tübingen, Germany.
++
++  He also offered a patch, which I could not take for fetchmail 6.4 because
++  it required a C99 system and I'd promised earlier that 6.4 would remain
++  compatible with C89 systems.
++--------------------------------------------------------------------------------
+ fetchmail-6.4.16 (released 2021-02-08, 27707 LoC):
+ 
+ # BUG FIXES
+diff --git a/report.c b/report.c
+index 1466802a..aea6b3ea 100644
+--- a/report.c
++++ b/report.c
+@@ -44,6 +44,8 @@ static unsigned int partial_message_size = 0;
+ static unsigned int partial_message_size_used = 0;
+ static char *partial_message;
+ static int partial_suppress_tag = 0;
++/* default size for the allocation of the report buffer */
++const size_t defaultsize = 4096;
+ 
+ static unsigned unbuffered;
+ static unsigned int use_syslog;
+@@ -177,6 +179,27 @@ void report_init(int mode /** 0: regular output, 1: unbuffered output, -1: syslo
+     }
+ }
+ 
++static void rep_ensuresize(size_t increment) {
++    if (partial_message_size == 0)
++    {
++	/* initialization */
++	partial_message_size_used = 0;
++	/* avoid too many small allocations initially */
++	if (increment < defaultsize) increment = defaultsize;
++	partial_message_size = increment;
++	partial_message = (char *)MALLOC (partial_message_size);
++    }
++    else /* already have buffer -> resize if too little room */
++    {
++	if (increment < defaultsize) increment = defaultsize;
++	if (partial_message_size - partial_message_size_used < increment)
++	{
++	    partial_message_size += increment;
++	    partial_message = (char *)REALLOC (partial_message, partial_message_size);
++	}
++    }
++}
++
+ /* Build an report message by appending MESSAGE, which is a printf-style
+    format string with optional args, to the existing report message (which may
+    be empty.)  The completed report message is finally printed (and reset to
+@@ -185,52 +208,37 @@ void report_init(int mode /** 0: regular output, 1: unbuffered output, -1: syslo
+    message exists, then, in an attempt to keep the messages in their proper
+    sequence, the partial message will be printed as-is (with a trailing 
+    newline) before report() prints its message. */
++
++
+ /* VARARGS */
++#ifdef HAVE_STDARG_H
++static int report_vgetsize(const char *message, va_list args)
++{
++    char tmp[1];
+ 
+-static void rep_ensuresize(void) {
+-    /* Make an initial guess for the size of any single message fragment.  */
+-    if (partial_message_size == 0)
+-    {
+-	partial_message_size_used = 0;
+-	partial_message_size = 2048;
+-	partial_message = (char *)MALLOC (partial_message_size);
+-    }
+-    else
+-	if (partial_message_size - partial_message_size_used < 1024)
+-	{
+-	    partial_message_size += 2048;
+-	    partial_message = (char *)REALLOC (partial_message, partial_message_size);
+-	}
++    return vsnprintf(tmp, 1, message, args);
+ }
+ 
+-#ifdef HAVE_STDARG_H
+-static void report_vbuild(const char *message, va_list args)
++/* note that report_vbuild assumes that the buffer was already allocated. */
++/* VARARGS */
++static int report_vbuild(const char *message, va_list args)
+ {
+     int n;
+ 
+-    for ( ; ; )
+-    {
+-	/*
+-	 * args has to be initialized before every call of vsnprintf(), 
+-	 * because vsnprintf() invokes va_arg macro and thus args is 
+-	 * undefined after the call.
+-	 */
+-	n = vsnprintf (partial_message + partial_message_size_used, partial_message_size - partial_message_size_used,
+-		       message, args);
+-
+-	/* output error, f. i. EILSEQ */
+-	if (n < 0) break;
+-
+-	if (n >= 0
+-	    && (unsigned)n < partial_message_size - partial_message_size_used)
+-        {
+-	    partial_message_size_used += n;
+-	    break;
+-	}
++    n = vsnprintf (partial_message + partial_message_size_used,
++		   partial_message_size - partial_message_size_used,
++		   message, args);
++
++    /* output error, f. i. EILSEQ */
++    if (n < 0)
++	    return -1;
+ 
+-	partial_message_size += 2048;
+-	partial_message = (char *)REALLOC (partial_message, partial_message_size);
++    if (n > 0)
++    {
++	partial_message_size_used += n;
+     }
++
++    return n;
+ }
+ #endif
+ 
+@@ -243,40 +251,45 @@ report_build (FILE *errfp, message, va_alist)
+      va_dcl
+ #endif
+ {
++    int n;
+ #ifdef VA_START
+     va_list args;
+-#else
+-    int n;
+ #endif
+ 
+-    rep_ensuresize();
++/* the logic is to first calculate the size,
++ * then reallocate, then fill the buffer
++ */
+ 
+ #if defined(VA_START)
+     VA_START(args, message);
+-    report_vbuild(message, args);
++    n = report_vgetsize(message, args);
+     va_end(args);
+-#else
+-    for ( ; ; )
+-    {
+-	n = snprintf (partial_message + partial_message_size_used,
+-		      partial_message_size - partial_message_size_used,
+-		      message, a1, a2, a3, a4, a5, a6, a7, a8);
+ 
+-	/* output error, f. i. EILSEQ */
+-	if (n < 0) break;
++    rep_ensuresize(n + 1);
+ 
+-	if (n >= 0
+-	    && (unsigned)n < partial_message_size - partial_message_size_used)
+-        {
+-	    partial_message_size_used += n;
+-	    break;
+-	}
++    VA_START(args, message);
++    n = report_vbuild(message, args);
++    va_end(args);
++#else
++    { 
++	char tmp[1];
++	/* note that SUSv2 specifies that with the 2nd argument zero, an 
++	 * unspecified value less than 1 were to be returned. This is not 
++	 * useful, so pass 1. */
++	n = snprintf (tmp, 1, 
++		      message, a1, a2, a3, a4, a5, a6, a7, a8);
+ 
+-	partial_message_size += 2048;
+-	partial_message = REALLOC (partial_message, partial_message_size);
++	if (n > 0)
++	    rep_ensuresize(n + 1);
+     }
++       
++    n = snprintf (partial_message + partial_message_size_used,
++		    partial_message_size - partial_message_size_used,
++		    message, a1, a2, a3, a4, a5, a6, a7, a8);
+ #endif
+ 
++    if (n > 0) partial_message_size_used += n;
++
+     if (unbuffered && partial_message_size_used != 0)
+     {
+ 	partial_message_size_used = 0;
+@@ -308,15 +321,18 @@ report_complete (FILE *errfp, message, va_alist)
+      va_dcl
+ #endif
+ {
++    int n;
+ #ifdef VA_START
+     va_list args;
+-#endif
+ 
+-    rep_ensuresize();
++    VA_START(args, message);
++    n = report_vgetsize(message, args);
++    va_end(args);
++
++    rep_ensuresize(n + 1);
+ 
+-#if defined(VA_START)
+     VA_START(args, message);
+-    report_vbuild(message, args);
++    n = report_vbuild(message, args);
+     va_end(args);
+ #else
+     report_build(errfp, message, a1, a2, a3, a4, a5, a6, a7, a8);
+-- 
+GitLab
+
diff -Nru fetchmail-6.4.16/debian/patches/series fetchmail-6.4.16/debian/patches/series
--- fetchmail-6.4.16/debian/patches/series	2021-06-24 19:00:48.000000000 +0200
+++ fetchmail-6.4.16/debian/patches/series	2021-07-29 00:18:56.000000000 +0200
@@ -4,3 +4,4 @@
 08_remove_forced_OpenSSL_check.patch
 09_fix_memory_leak_in_timeout_situation.patch
 10_update_manpage.patch
+11_fix_CVE-2021-38386.patch

Reply to: