summaryrefslogtreecommitdiffstats
path: root/debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch102
1 files changed, 102 insertions, 0 deletions
diff --git a/debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch b/debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch
new file mode 100644
index 0000000..3864de2
--- /dev/null
+++ b/debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch
@@ -0,0 +1,102 @@
+From 327f647a849c3974e7107b5386421b0058c15b29 Mon Sep 17 00:00:00 2001
+From: Qualys Security Advisory <qsa@qualys.com>
+Date: Sun, 21 Feb 2021 21:17:31 -0800
+Subject: [PATCH 10/29] CVE-2020-28026: Line truncation and injection in
+ spool_read_header()
+
+This also fixes:
+
+2/ In src/spool_in.c:
+
+ 462 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
+ 463 && big_buffer[len-1] != '\n'
+ 464 )
+ 465 { /* buffer not big enough for line; certs make this possible */
+ 466 uschar * buf;
+ 467 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
+ 468 buf = store_get_perm(big_buffer_size *= 2, FALSE);
+ 469 memcpy(buf, big_buffer, --len);
+
+The --len in memcpy() chops off a useful byte (we know for sure that
+big_buffer[len-1] is not a '\n' because we entered the while loop).
+---
+ src/spool_in.c | 48 +++++++++++++++++++++++++++++++---------------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+diff --git a/src/spool_in.c b/src/spool_in.c
+index 2d349778c..dbbcf23ee 100644
+--- a/src/spool_in.c
++++ b/src/spool_in.c
+@@ -307,6 +307,36 @@ dsn_ret = 0;
+ dsn_envid = NULL;
+ }
+
++static void *
++fgets_big_buffer(FILE *fp)
++{
++int len = 0;
++
++big_buffer[0] = 0;
++if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) return NULL;
++
++while ((len = Ustrlen(big_buffer)) == big_buffer_size-1
++ && big_buffer[len-1] != '\n')
++ {
++ uschar *newbuffer;
++ int newsize;
++
++ if (big_buffer_size >= BIG_BUFFER_SIZE * 4) return NULL;
++ newsize = big_buffer_size * 2;
++ newbuffer = store_get_perm(newsize);
++ memcpy(newbuffer, big_buffer, len);
++
++ big_buffer = newbuffer;
++ big_buffer_size = newsize;
++ if (Ufgets(big_buffer + len, big_buffer_size - len, fp) == NULL) return NULL;
++ }
++
++if (len <= 0 || big_buffer[len-1] != '\n') return NULL;
++return big_buffer;
++}
++
++
++
+
+ /*************************************************
+ * Read spool header file *
+@@ -450,21 +480,9 @@ p = big_buffer + 2;
+ for (;;)
+ {
+ int len;
+- if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
++ if (fgets_big_buffer(fp) == NULL) goto SPOOL_READ_ERROR;
+ if (big_buffer[0] != '-') break;
+- while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
+- && big_buffer[len-1] != '\n'
+- )
+- { /* buffer not big enough for line; certs make this possible */
+- uschar * buf;
+- if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
+- buf = store_get_perm(big_buffer_size *= 2);
+- memcpy(buf, big_buffer, --len);
+- big_buffer = buf;
+- if (Ufgets(big_buffer+len, big_buffer_size-len, fp) == NULL)
+- goto SPOOL_READ_ERROR;
+- }
+- big_buffer[len-1] = 0;
++ big_buffer[Ustrlen(big_buffer)-1] = 0;
+
+ switch(big_buffer[1])
+ {
+@@ -724,7 +742,7 @@ DEBUG(D_deliver)
+ buffer. It contains the count of recipients which follow on separate lines.
+ Apply an arbitrary sanity check.*/
+
+-if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
++if (fgets_big_buffer(fp) == NULL) goto SPOOL_READ_ERROR;
+ if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
+ goto SPOOL_FORMAT_ERROR;
+
+--
+2.30.2
+