diff options
Diffstat (limited to 'debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch')
-rw-r--r-- | debian/patches/84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch | 102 |
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 + |