diff --git a/package/exim/0006-Fix-regex-n-use-after-free.-Bug-2915.patch b/package/exim/0006-Fix-regex-n-use-after-free.-Bug-2915.patch new file mode 100644 index 0000000000..57fa189b04 --- /dev/null +++ b/package/exim/0006-Fix-regex-n-use-after-free.-Bug-2915.patch @@ -0,0 +1,173 @@ +From 4e9ed49f8f12eb331b29bd5b6dc3693c520fddc2 Mon Sep 17 00:00:00 2001 +From: Jeremy Harris +Date: Wed, 31 Aug 2022 15:37:40 +0100 +Subject: [PATCH] Fix $regex use-after-free. Bug 2915 + +[Upstream: https://sources.debian.org/data/main/e/exim4/4.96-9/debian/patches/75_08-Fix-regex-n-use-after-free.-Bug-2915.patch] +[Peter: drop Changelog hunk] +Signed-off-by: Peter Korsgaard +--- + src/exim.c | 4 +--- + src/expand.c | 2 +- + src/functions.h | 1 + + src/globals.c | 2 +- + src/regex.c | 29 ++++++++++++++++++----------- + src/smtp_in.c | 2 ++ + test/confs/4002 | 10 ++++++++++ + test/mail/4002.userx | 7 +++++++ + test/scripts/4000-scanning/4002 | 7 +++++++ + 9 files changed, 53 insertions(+), 17 deletions(-) + +--- a/src/exim.c ++++ b/src/exim.c +@@ -1999,12 +1999,10 @@ + + regex_whitelisted_macro = + regex_must_compile(US"^[A-Za-z0-9_/.-]*$", FALSE, TRUE); + #endif + +-for (i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; +- + /* If the program is called as "mailq" treat it as equivalent to "exim -bp"; + this seems to be a generally accepted convention, since one finds symbolic + links called "mailq" in standard OS configurations. */ + + if ((namelen == 5 && Ustrcmp(argv[0], "mailq") == 0) || +@@ -6082,11 +6080,11 @@ + callout_address = NULL; + sending_ip_address = NULL; + deliver_localpart_data = deliver_domain_data = + recipient_data = sender_data = NULL; + acl_var_m = NULL; +- for(int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; ++ regex_vars_clear(); + + store_reset(reset_point); + } + + exim_exit(EXIT_SUCCESS); /* Never returns */ +--- a/src/expand.c ++++ b/src/expand.c +@@ -1871,11 +1871,11 @@ + { + tree_node * node = tree_search(router_var, name + 2); + return node ? node->data.ptr : strict_acl_vars ? NULL : US""; + } + +-/* Handle $auth variables. */ ++/* Handle $auth, $regex variables. */ + + if (Ustrncmp(name, "auth", 4) == 0) + { + uschar *endptr; + int n = Ustrtoul(name + 4, &endptr, 10); +--- a/src/functions.h ++++ b/src/functions.h +@@ -436,10 +436,11 @@ + extern int regex(const uschar **); + #endif + extern BOOL regex_match(const pcre2_code *, const uschar *, int, uschar **); + extern BOOL regex_match_and_setup(const pcre2_code *, const uschar *, int, int); + extern const pcre2_code *regex_must_compile(const uschar *, BOOL, BOOL); ++extern void regex_vars_clear(void); + extern void retry_add_item(address_item *, uschar *, int); + extern BOOL retry_check_address(const uschar *, host_item *, uschar *, BOOL, + uschar **, uschar **); + extern retry_config *retry_find_config(const uschar *, const uschar *, int, int); + extern BOOL retry_ultimate_address_timeout(uschar *, const uschar *, +--- a/src/globals.c ++++ b/src/globals.c +@@ -1313,11 +1313,11 @@ + #ifndef DISABLE_PIPE_CONNECT + const pcre2_code *regex_EARLY_PIPE = NULL; + #endif + const pcre2_code *regex_ismsgid = NULL; + const pcre2_code *regex_smtp_code = NULL; +-const uschar *regex_vars[REGEX_VARS]; ++const uschar *regex_vars[REGEX_VARS] = { 0 };; + #ifdef WHITELIST_D_MACROS + const pcre2_code *regex_whitelisted_macro = NULL; + #endif + #ifdef WITH_CONTENT_SCAN + uschar *regex_match_string = NULL; +--- a/src/regex.c ++++ b/src/regex.c +@@ -94,22 +94,32 @@ + } + pcre2_match_data_free(md); + return FAIL; + } + ++ ++/* reset expansion variables */ ++void ++regex_vars_clear(void) ++{ ++regex_match_string = NULL; ++for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; ++} ++ ++ ++ + int +-regex(const uschar **listptr) ++regex(const uschar ** listptr) + { + unsigned long mbox_size; +-FILE *mbox_file; +-pcre_list *re_list_head; +-uschar *linebuffer; ++FILE * mbox_file; ++pcre_list * re_list_head; ++uschar * linebuffer; + long f_pos = 0; + int ret = FAIL; + +-/* reset expansion variable */ +-regex_match_string = NULL; ++regex_vars_clear(); + + if (!mime_stream) /* We are in the DATA ACL */ + { + if (!(mbox_file = spool_mbox(&mbox_size, NULL, NULL))) + { /* error while spooling */ +@@ -167,18 +177,17 @@ + + + int + mime_regex(const uschar **listptr) + { +-pcre_list *re_list_head = NULL; +-FILE *f; +-uschar *mime_subject = NULL; ++pcre_list * re_list_head = NULL; ++FILE * f; ++uschar * mime_subject = NULL; + int mime_subject_len = 0; + int ret; + +-/* reset expansion variable */ +-regex_match_string = NULL; ++regex_vars_clear(); + + /* precompile our regexes */ + if (!(re_list_head = compile(*listptr))) + return FAIL; /* no regexes -> nothing to do */ + +--- a/src/smtp_in.c ++++ b/src/smtp_in.c +@@ -2155,12 +2155,14 @@ + prdr_requested = FALSE; + #endif + #ifdef SUPPORT_I18N + message_smtputf8 = FALSE; + #endif ++regex_vars_clear(); + body_linecount = body_zerocount = 0; + ++lookup_value = NULL; /* Can be set by ACL */ + sender_rate = sender_rate_limit = sender_rate_period = NULL; + ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */ + /* Note that ratelimiters_conn persists across resets. */ + + /* Reset message ACL variables */ diff --git a/package/exim/0007-Fix-non-WITH_CONTENT_SCAN-build.patch b/package/exim/0007-Fix-non-WITH_CONTENT_SCAN-build.patch new file mode 100644 index 0000000000..9f87f18e00 --- /dev/null +++ b/package/exim/0007-Fix-non-WITH_CONTENT_SCAN-build.patch @@ -0,0 +1,61 @@ +From d8ecc7bf97934a1e2244788c610c958cacd740bd Mon Sep 17 00:00:00 2001 +From: Jeremy Harris +Date: Wed, 31 Aug 2022 17:03:37 +0100 +Subject: [PATCH] Fix non-WITH_CONTENT_SCAN build. + +Broken-by: 4e9ed49f8f + +[Upstream: https://sources.debian.org/data/main/e/exim4/4.96-9/debian/patches/75_09-Fix-non-WITH_CONTENT_SCAN-build.patch] +Signed-off-by: Peter Korsgaard +--- + src/exim.c | 11 +++++++++++ + src/regex.c | 10 ---------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +--- a/src/exim.c ++++ b/src/exim.c +@@ -1677,10 +1677,21 @@ + if ((s = expand_string(big_buffer))) printf("%s\n", CS s); + else printf("Failed: %s\n", expand_string_message); + } + + ++/* reset regex expansion variables */ ++void ++regex_vars_clear(void) ++{ ++regex_match_string = NULL; ++for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; ++} ++ ++ ++ ++ + + /************************************************* + * Entry point and high-level code * + *************************************************/ + +--- a/src/regex.c ++++ b/src/regex.c +@@ -95,20 +95,10 @@ + pcre2_match_data_free(md); + return FAIL; + } + + +-/* reset expansion variables */ +-void +-regex_vars_clear(void) +-{ +-regex_match_string = NULL; +-for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; +-} +- +- +- + int + regex(const uschar ** listptr) + { + unsigned long mbox_size; + FILE * mbox_file; diff --git a/package/exim/0008-Fix-non-WITH_CONTENT_SCAN-build-2.patch b/package/exim/0008-Fix-non-WITH_CONTENT_SCAN-build-2.patch new file mode 100644 index 0000000000..43cc1d79a9 --- /dev/null +++ b/package/exim/0008-Fix-non-WITH_CONTENT_SCAN-build-2.patch @@ -0,0 +1,139 @@ +From 158dff9936e36a2d31d037d3988b9353458d6471 Mon Sep 17 00:00:00 2001 +From: Jeremy Harris +Date: Wed, 31 Aug 2022 17:17:59 +0100 +Subject: [PATCH] Fix non-WITH_CONTENT_SCAN build (2) + +Broken-by: d8ecc7bf97 + +[Upstream: https://sources.debian.org/data/main/e/exim4/4.96-9/debian/patches/75_10-Fix-non-WITH_CONTENT_SCAN-build-2.patch] +[Peter: drop Changelog hunk] +Signed-off-by: Peter Korsgaard +--- + src/exim.c | 13 +------------ + src/functions.h | 2 +- + src/globals.h | 2 +- + src/regex.c | 10 ++++++++++ + src/smtp_in.c | 2 ++ + 5 files changed, 15 insertions(+), 14 deletions(-) + +--- a/src/exim.c ++++ b/src/exim.c +@@ -1677,21 +1677,10 @@ + if ((s = expand_string(big_buffer))) printf("%s\n", CS s); + else printf("Failed: %s\n", expand_string_message); + } + + +-/* reset regex expansion variables */ +-void +-regex_vars_clear(void) +-{ +-regex_match_string = NULL; +-for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; +-} +- +- +- +- + + /************************************************* + * Entry point and high-level code * + *************************************************/ + +@@ -6085,17 +6074,17 @@ + deliver_domain_orig = NULL; + deliver_host = deliver_host_address = NULL; + dnslist_domain = dnslist_matched = NULL; + #ifdef WITH_CONTENT_SCAN + malware_name = NULL; ++ regex_vars_clear(); + #endif + callout_address = NULL; + sending_ip_address = NULL; + deliver_localpart_data = deliver_domain_data = + recipient_data = sender_data = NULL; + acl_var_m = NULL; +- regex_vars_clear(); + + store_reset(reset_point); + } + + exim_exit(EXIT_SUCCESS); /* Never returns */ +--- a/src/functions.h ++++ b/src/functions.h +@@ -432,15 +432,15 @@ + extern BOOL receive_msg(BOOL); + extern int_eximarith_t receive_statvfs(BOOL, int *); + extern void receive_swallow_smtp(void); + #ifdef WITH_CONTENT_SCAN + extern int regex(const uschar **); ++extern void regex_vars_clear(void); + #endif + extern BOOL regex_match(const pcre2_code *, const uschar *, int, uschar **); + extern BOOL regex_match_and_setup(const pcre2_code *, const uschar *, int, int); + extern const pcre2_code *regex_must_compile(const uschar *, BOOL, BOOL); +-extern void regex_vars_clear(void); + extern void retry_add_item(address_item *, uschar *, int); + extern BOOL retry_check_address(const uschar *, host_item *, uschar *, BOOL, + uschar **, uschar **); + extern retry_config *retry_find_config(const uschar *, const uschar *, int, int); + extern BOOL retry_ultimate_address_timeout(uschar *, const uschar *, +--- a/src/globals.h ++++ b/src/globals.h +@@ -895,16 +895,16 @@ + #ifndef DISABLE_PIPE_CONNECT + extern const pcre2_code *regex_EARLY_PIPE; /* For recognizing PIPE_CONNCT */ + #endif + extern const pcre2_code *regex_ismsgid; /* Compiled r.e. for message ID */ + extern const pcre2_code *regex_smtp_code; /* For recognizing SMTP codes */ +-extern const uschar *regex_vars[]; /* $regexN variables */ + #ifdef WHITELIST_D_MACROS + extern const pcre2_code *regex_whitelisted_macro; /* For -D macro values */ + #endif + #ifdef WITH_CONTENT_SCAN + extern uschar *regex_match_string; /* regex that matched a line (regex ACL condition) */ ++extern const uschar *regex_vars[]; + #endif + extern int remote_delivery_count; /* Number of remote addresses */ + extern int remote_max_parallel; /* Maximum parallel delivery */ + extern uschar *remote_sort_domains; /* Remote domain sorting order */ + extern retry_config *retries; /* Chain of retry config information */ +--- a/src/regex.c ++++ b/src/regex.c +@@ -95,10 +95,20 @@ + pcre2_match_data_free(md); + return FAIL; + } + + ++/* reset expansion variables */ ++void ++regex_vars_clear(void) ++{ ++regex_match_string = NULL; ++for (int i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL; ++} ++ ++ ++ + int + regex(const uschar ** listptr) + { + unsigned long mbox_size; + FILE * mbox_file; +--- a/src/smtp_in.c ++++ b/src/smtp_in.c +@@ -2155,11 +2155,13 @@ + prdr_requested = FALSE; + #endif + #ifdef SUPPORT_I18N + message_smtputf8 = FALSE; + #endif ++#ifdef WITH_CONTENT_SCAN + regex_vars_clear(); ++#endif + body_linecount = body_zerocount = 0; + + lookup_value = NULL; /* Can be set by ACL */ + sender_rate = sender_rate_limit = sender_rate_period = NULL; + ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */ diff --git a/package/exim/0009-Fix-non-WITH_CONTENT_SCAN-build-3.patch b/package/exim/0009-Fix-non-WITH_CONTENT_SCAN-build-3.patch new file mode 100644 index 0000000000..f9675c80d3 --- /dev/null +++ b/package/exim/0009-Fix-non-WITH_CONTENT_SCAN-build-3.patch @@ -0,0 +1,49 @@ +From 32da6327e434e986a18b75a84f2d8c687ba14619 Mon Sep 17 00:00:00 2001 +From: Jeremy Harris +Date: Thu, 1 Sep 2022 15:54:35 +0100 +Subject: [PATCH] Fix non-WITH_CONTENT_SCAN build (3) + +Broken-by: d8ecc7bf97 + +[Upstream: https://sources.debian.org/data/main/e/exim4/4.96-9/debian/patches/75_11-Fix-non-WITH_CONTENT_SCAN-build-3.patch] +[Peter: drop Changelog hunk] +Signed-off-by: Peter Korsgaard +--- + src/expand.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/expand.c b/src/expand.c +index 89de56255..831ca2b75 100644 +--- a/src/expand.c ++++ b/src/expand.c +@@ -1869,6 +1869,7 @@ if (Ustrncmp(name, "auth", 4) == 0) + if (!*endptr && n != 0 && n <= AUTH_VARS) + return auth_vars[n-1] ? auth_vars[n-1] : US""; + } ++#ifdef WITH_CONTENT_SCAN + else if (Ustrncmp(name, "regex", 5) == 0) + { + uschar *endptr; +@@ -1876,6 +1877,7 @@ else if (Ustrncmp(name, "regex", 5) == 0) + if (!*endptr && n != 0 && n <= REGEX_VARS) + return regex_vars[n-1] ? regex_vars[n-1] : US""; + } ++#endif + + /* For all other variables, search the table */ + +@@ -8715,9 +8717,11 @@ assert_variable_notin() treats as const, so deconst is safe. */ + for (int i = 0; i < AUTH_VARS; i++) if (auth_vars[i]) + assert_variable_notin(US"auth", US auth_vars[i], &e); + ++#ifdef WITH_CONTENT_SCAN + /* check regex variables. assert_variable_notin() treats as const. */ + for (int i = 0; i < REGEX_VARS; i++) if (regex_vars[i]) + assert_variable_notin(US"regex", US regex_vars[i], &e); ++#endif + + /* check known-name variables */ + for (var_entry * v = var_table; v < var_table + var_table_size; v++) +-- +2.35.1 + diff --git a/package/exim/exim.mk b/package/exim/exim.mk index 9c54eeec44..cd2fabeab1 100644 --- a/package/exim/exim.mk +++ b/package/exim/exim.mk @@ -13,6 +13,9 @@ EXIM_CPE_ID_VENDOR = exim EXIM_SELINUX_MODULES = exim mta EXIM_DEPENDENCIES = host-berkeleydb host-pcre2 pcre2 berkeleydb host-pkgconf +# 0006-Fix-regex-n-use-after-free.-Bug-2915.patch +EXIM_IGNORE_CVES += CVE-2022-3559 + # Modify a variable value. It must already exist in the file, either # commented or not. define exim-config-change # variable-name, variable-value