Import Debian changes 4.92-8+deb10u6
[hcoop/debian/exim4.git] / debian / patches / 84_10-CVE-2020-28026-Line-truncation-and-injection-in-spoo.patch
1 From 327f647a849c3974e7107b5386421b0058c15b29 Mon Sep 17 00:00:00 2001
2 From: Qualys Security Advisory <qsa@qualys.com>
3 Date: Sun, 21 Feb 2021 21:17:31 -0800
4 Subject: [PATCH 10/29] CVE-2020-28026: Line truncation and injection in
5 spool_read_header()
6
7 This also fixes:
8
9 2/ In src/spool_in.c:
10
11 462 while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
12 463 && big_buffer[len-1] != '\n'
13 464 )
14 465 { /* buffer not big enough for line; certs make this possible */
15 466 uschar * buf;
16 467 if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
17 468 buf = store_get_perm(big_buffer_size *= 2, FALSE);
18 469 memcpy(buf, big_buffer, --len);
19
20 The --len in memcpy() chops off a useful byte (we know for sure that
21 big_buffer[len-1] is not a '\n' because we entered the while loop).
22 ---
23 src/spool_in.c | 48 +++++++++++++++++++++++++++++++---------------
24 1 file changed, 33 insertions(+), 15 deletions(-)
25
26 diff --git a/src/spool_in.c b/src/spool_in.c
27 index 2d349778c..dbbcf23ee 100644
28 --- a/src/spool_in.c
29 +++ b/src/spool_in.c
30 @@ -307,6 +307,36 @@ dsn_ret = 0;
31 dsn_envid = NULL;
32 }
33
34 +static void *
35 +fgets_big_buffer(FILE *fp)
36 +{
37 +int len = 0;
38 +
39 +big_buffer[0] = 0;
40 +if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) return NULL;
41 +
42 +while ((len = Ustrlen(big_buffer)) == big_buffer_size-1
43 + && big_buffer[len-1] != '\n')
44 + {
45 + uschar *newbuffer;
46 + int newsize;
47 +
48 + if (big_buffer_size >= BIG_BUFFER_SIZE * 4) return NULL;
49 + newsize = big_buffer_size * 2;
50 + newbuffer = store_get_perm(newsize);
51 + memcpy(newbuffer, big_buffer, len);
52 +
53 + big_buffer = newbuffer;
54 + big_buffer_size = newsize;
55 + if (Ufgets(big_buffer + len, big_buffer_size - len, fp) == NULL) return NULL;
56 + }
57 +
58 +if (len <= 0 || big_buffer[len-1] != '\n') return NULL;
59 +return big_buffer;
60 +}
61 +
62 +
63 +
64
65 /*************************************************
66 * Read spool header file *
67 @@ -450,21 +480,9 @@ p = big_buffer + 2;
68 for (;;)
69 {
70 int len;
71 - if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
72 + if (fgets_big_buffer(fp) == NULL) goto SPOOL_READ_ERROR;
73 if (big_buffer[0] != '-') break;
74 - while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
75 - && big_buffer[len-1] != '\n'
76 - )
77 - { /* buffer not big enough for line; certs make this possible */
78 - uschar * buf;
79 - if (big_buffer_size >= BIG_BUFFER_SIZE*4) goto SPOOL_READ_ERROR;
80 - buf = store_get_perm(big_buffer_size *= 2);
81 - memcpy(buf, big_buffer, --len);
82 - big_buffer = buf;
83 - if (Ufgets(big_buffer+len, big_buffer_size-len, fp) == NULL)
84 - goto SPOOL_READ_ERROR;
85 - }
86 - big_buffer[len-1] = 0;
87 + big_buffer[Ustrlen(big_buffer)-1] = 0;
88
89 switch(big_buffer[1])
90 {
91 @@ -724,7 +742,7 @@ DEBUG(D_deliver)
92 buffer. It contains the count of recipients which follow on separate lines.
93 Apply an arbitrary sanity check.*/
94
95 -if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
96 +if (fgets_big_buffer(fp) == NULL) goto SPOOL_READ_ERROR;
97 if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
98 goto SPOOL_FORMAT_ERROR;
99
100 --
101 2.30.2
102