| From 4e9ed49f8f12eb331b29bd5b6dc3693c520fddc2 Mon Sep 17 00:00:00 2001 |
| From: Jeremy Harris <jgh146exb@wizmail.org> |
| Date: Wed, 31 Aug 2022 15:37:40 +0100 |
| Subject: [PATCH] Fix $regex<n> 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 <peter@korsgard.com> |
| --- |
| 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<n> variables. */ |
| +/* Handle $auth<n>, $regex<n> 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 */ |