summaryrefslogtreecommitdiffstats
path: root/debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch')
-rw-r--r--debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch135
1 files changed, 135 insertions, 0 deletions
diff --git a/debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch b/debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch
new file mode 100644
index 0000000..0d44293
--- /dev/null
+++ b/debian/patches/84_22-CVE-2020-28019-Failure-to-reset-function-pointer-aft.patch
@@ -0,0 +1,135 @@
+From 1663ab541b37675dec5bcf235605568ff36ac65a Mon Sep 17 00:00:00 2001
+From: Qualys Security Advisory <qsa@qualys.com>
+Date: Sun, 21 Feb 2021 22:36:10 -0800
+Subject: [PATCH 22/29] CVE-2020-28019: Failure to reset function pointer after
+ BDAT error
+
+Based on Phil Pennock's commits 4715403e and 151ffd72, and Jeremy
+Harris's commits aa171254 and 9aceb5c2.
+---
+ src/globals.c | 1 +
+ src/globals.h | 1 +
+ src/smtp_in.c | 55 +++++++++++++++++++++++++++++++++++++++--------
+ 3 files changed, 48 insertions(+), 9 deletions(-)
+
+diff --git a/src/globals.c b/src/globals.c
+index b3362a34c..894b8487b 100644
+--- a/src/globals.c
++++ b/src/globals.c
+@@ -247,6 +247,7 @@ struct global_flags f =
+ .authentication_local = FALSE,
+
+ .background_daemon = TRUE,
++ .bdat_readers_wanted = FALSE,
+
+ .chunking_offered = FALSE,
+ .config_changed = FALSE,
+diff --git a/src/globals.h b/src/globals.h
+index f71f104e2..58f7ae55f 100644
+--- a/src/globals.h
++++ b/src/globals.h
+@@ -173,6 +173,7 @@ extern struct global_flags {
+ BOOL authentication_local :1; /* TRUE if non-smtp (implicit authentication) */
+
+ BOOL background_daemon :1; /* Set FALSE to keep in foreground */
++ BOOL bdat_readers_wanted :1; /* BDAT-handling to be pushed on readfunc stack */
+
+ BOOL chunking_offered :1;
+ BOOL config_changed :1; /* True if -C used */
+diff --git a/src/smtp_in.c b/src/smtp_in.c
+index 1a5fbfea3..016c44c0f 100644
+--- a/src/smtp_in.c
++++ b/src/smtp_in.c
+@@ -602,6 +602,10 @@ if (n > 0)
+ #endif
+ }
+
++/* Forward declarations */
++static inline void bdat_push_receive_functions(void);
++static inline void bdat_pop_receive_functions(void);
++
+
+ /* Get a byte from the smtp input, in CHUNKING mode. Handle ack of the
+ previous BDAT chunk and getting new ones when we run out. Uses the
+@@ -634,9 +638,7 @@ for(;;)
+ if (chunking_data_left > 0)
+ return lwr_receive_getc(chunking_data_left--);
+
+- receive_getc = lwr_receive_getc;
+- receive_getbuf = lwr_receive_getbuf;
+- receive_ungetc = lwr_receive_ungetc;
++ bdat_pop_receive_functions();
+ #ifndef DISABLE_DKIM
+ dkim_save = dkim_collect_input;
+ dkim_collect_input = 0;
+@@ -740,9 +742,7 @@ next_cmd:
+ goto repeat_until_rset;
+ }
+
+- receive_getc = bdat_getc;
+- receive_getbuf = bdat_getbuf; /* r~getbuf is never actually used */
+- receive_ungetc = bdat_ungetc;
++ bdat_push_receive_functions();
+ #ifndef DISABLE_DKIM
+ dkim_collect_input = dkim_save;
+ #endif
+@@ -775,9 +775,7 @@ while (chunking_data_left)
+ if (!bdat_getbuf(&n)) break;
+ }
+
+-receive_getc = lwr_receive_getc;
+-receive_getbuf = lwr_receive_getbuf;
+-receive_ungetc = lwr_receive_ungetc;
++bdat_pop_receive_functions();
+
+ if (chunking_state != CHUNKING_LAST)
+ {
+@@ -787,6 +785,45 @@ if (chunking_state != CHUNKING_LAST)
+ }
+
+
++static inline void
++bdat_push_receive_functions(void)
++{
++/* push the current receive_* function on the "stack", and
++replace them by bdat_getc(), which in turn will use the lwr_receive_*
++functions to do the dirty work. */
++if (lwr_receive_getc == NULL)
++ {
++ lwr_receive_getc = receive_getc;
++ lwr_receive_getbuf = receive_getbuf;
++ lwr_receive_ungetc = receive_ungetc;
++ }
++else
++ {
++ DEBUG(D_receive) debug_printf("chunking double-push receive functions\n");
++ }
++
++receive_getc = bdat_getc;
++receive_getbuf = bdat_getbuf;
++receive_ungetc = bdat_ungetc;
++}
++
++static inline void
++bdat_pop_receive_functions(void)
++{
++if (lwr_receive_getc == NULL)
++ {
++ DEBUG(D_receive) debug_printf("chunking double-pop receive functions\n");
++ return;
++ }
++
++receive_getc = lwr_receive_getc;
++receive_getbuf = lwr_receive_getbuf;
++receive_ungetc = lwr_receive_ungetc;
++
++lwr_receive_getc = NULL;
++lwr_receive_getbuf = NULL;
++lwr_receive_ungetc = NULL;
++}
+
+
+ /*************************************************
+--
+2.30.2
+