Import Debian changes 4.92-8+deb10u6
[hcoop/debian/exim4.git] / debian / patches / 84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch
1 From 1663ab541b37675dec5bcf235605568ff36ac65a Mon Sep 17 00:00:00 2001
2 From: Qualys Security Advisory <qsa@qualys.com>
3 Date: Sun, 21 Feb 2021 22:36:10 -0800
4 Subject: [PATCH 22/29] CVE-2020-28019: Failure to reset function pointer after
5 BDAT error
6
7 Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy
8 Harris's commits aa171254 and 9aceb5c2.
9 ---
10 src/globals.c | 1 +
11 src/globals.h | 1 +
12 src/smtp_in.c | 55 +++++++++++++++++++++++++++++++++++++++--------
13 3 files changed, 48 insertions(+), 9 deletions(-)
14
15 diff --git a/src/globals.c b/src/globals.c
16 index b3362a34c..894b8487b 100644
17 --- a/src/globals.c
18 +++ b/src/globals.c
19 @@ -247,6 +247,7 @@ struct global_flags f =
20 .authentication_local = FALSE,
21
22 .background_daemon = TRUE,
23 + .bdat_readers_wanted = FALSE,
24
25 .chunking_offered = FALSE,
26 .config_changed = FALSE,
27 diff --git a/src/globals.h b/src/globals.h
28 index f71f104e2..58f7ae55f 100644
29 --- a/src/globals.h
30 +++ b/src/globals.h
31 @@ -173,6 +173,7 @@ extern struct global_flags {
32 BOOL authentication_local :1; /* TRUE if non-smtp (implicit authentication) */
33
34 BOOL background_daemon :1; /* Set FALSE to keep in foreground */
35 + BOOL bdat_readers_wanted :1; /* BDAT-handling to be pushed on readfunc stack */
36
37 BOOL chunking_offered :1;
38 BOOL config_changed :1; /* True if -C used */
39 diff --git a/src/smtp_in.c b/src/smtp_in.c
40 index 1a5fbfea3..016c44c0f 100644
41 --- a/src/smtp_in.c
42 +++ b/src/smtp_in.c
43 @@ -602,6 +602,10 @@ if (n > 0)
44 #endif
45 }
46
47 +/* Forward declarations */
48 +static inline void bdat_push_receive_functions(void);
49 +static inline void bdat_pop_receive_functions(void);
50 +
51
52 /* Get a byte from the smtp input, in CHUNKING mode. Handle ack of the
53 previous BDAT chunk and getting new ones when we run out. Uses the
54 @@ -634,9 +638,7 @@ for(;;)
55 if (chunking_data_left > 0)
56 return lwr_receive_getc(chunking_data_left--);
57
58 - receive_getc = lwr_receive_getc;
59 - receive_getbuf = lwr_receive_getbuf;
60 - receive_ungetc = lwr_receive_ungetc;
61 + bdat_pop_receive_functions();
62 #ifndef DISABLE_DKIM
63 dkim_save = dkim_collect_input;
64 dkim_collect_input = 0;
65 @@ -740,9 +742,7 @@ next_cmd:
66 goto repeat_until_rset;
67 }
68
69 - receive_getc = bdat_getc;
70 - receive_getbuf = bdat_getbuf; /* r~getbuf is never actually used */
71 - receive_ungetc = bdat_ungetc;
72 + bdat_push_receive_functions();
73 #ifndef DISABLE_DKIM
74 dkim_collect_input = dkim_save;
75 #endif
76 @@ -775,9 +775,7 @@ while (chunking_data_left)
77 if (!bdat_getbuf(&n)) break;
78 }
79
80 -receive_getc = lwr_receive_getc;
81 -receive_getbuf = lwr_receive_getbuf;
82 -receive_ungetc = lwr_receive_ungetc;
83 +bdat_pop_receive_functions();
84
85 if (chunking_state != CHUNKING_LAST)
86 {
87 @@ -787,6 +785,45 @@ if (chunking_state != CHUNKING_LAST)
88 }
89
90
91 +static inline void
92 +bdat_push_receive_functions(void)
93 +{
94 +/* push the current receive_* function on the "stack", and
95 +replace them by bdat_getc(), which in turn will use the lwr_receive_*
96 +functions to do the dirty work. */
97 +if (lwr_receive_getc == NULL)
98 + {
99 + lwr_receive_getc = receive_getc;
100 + lwr_receive_getbuf = receive_getbuf;
101 + lwr_receive_ungetc = receive_ungetc;
102 + }
103 +else
104 + {
105 + DEBUG(D_receive) debug_printf("chunking double-push receive functions\n");
106 + }
107 +
108 +receive_getc = bdat_getc;
109 +receive_getbuf = bdat_getbuf;
110 +receive_ungetc = bdat_ungetc;
111 +}
112 +
113 +static inline void
114 +bdat_pop_receive_functions(void)
115 +{
116 +if (lwr_receive_getc == NULL)
117 + {
118 + DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
119 + return;
120 + }
121 +
122 +receive_getc = lwr_receive_getc;
123 +receive_getbuf = lwr_receive_getbuf;
124 +receive_ungetc = lwr_receive_ungetc;
125 +
126 +lwr_receive_getc = NULL;
127 +lwr_receive_getbuf = NULL;
128 +lwr_receive_ungetc = NULL;
129 +}
130
131
132 /*************************************************
133 --
134 2.30.2
135