summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2022-08-31 15:37:40 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2022-08-31 15:57:29 +0100
commit4e9ed49f8f12eb331b29bd5b6dc3693c520fddc2 (patch)
treef8041218c4d3a259b1a5c5b72ad944424f40a922
parent1072af868662ea8fec30454c2d62afdee24f2c8e (diff)
downloadexim4-4e9ed49f8f12eb331b29bd5b6dc3693c520fddc2.tar.gz
Fix $regex<n> use-after-free. Bug 2915
-rw-r--r--doc/doc-txt/ChangeLog8
-rw-r--r--src/src/exim.c4
-rw-r--r--src/src/expand.c2
-rw-r--r--src/src/functions.h1
-rw-r--r--src/src/globals.c2
-rw-r--r--src/src/regex.c29
-rw-r--r--src/src/smtp_in.c2
-rw-r--r--test/confs/400210
-rw-r--r--test/mail/4002.userx7
-rw-r--r--test/scripts/4000-scanning/40027
10 files changed, 55 insertions, 17 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 6a4e10915..ba5bd23d9 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -30,11 +30,17 @@ JH/07 OpenSSL Fix auto-reload of changed server OCSP proof. Previously, if
the file with the proof had an unchanged name, the new proof(s) were
loaded on top of the old ones (and nover used; the old ones were stapled).
+JH/08 Bug 2915: Fix use-after-free for $regex<n> variables. Previously when
+ more than one message arrived in a single connection a reference from
+ the earlier message could be re-used. Often a sigsegv resulted.
+ These variables were introduced in Exim 4.87.
+ Debug help from Graeme Fowler.
+
Exim version 4.96
-----------------
-JH/01 Move the wait-for-next-tick (needed for unique messmage IDs) from
+JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
after reception to before a subsequent reception. This should
mean slightly faster delivery, and also confirmation of reception
to senders.
diff --git a/src/src/exim.c b/src/src/exim.c
index ea4286af3..b9328f017 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -2000,8 +2000,6 @@ regex_whitelisted_macro =
regex_must_compile(US"^[A-Za-z0-9_/.-]*$", MCS_NOFLAGS, 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. */
@@ -6089,7 +6087,7 @@ MORELOOP:
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);
}
diff --git a/src/src/expand.c b/src/src/expand.c
index ffbdc14e5..89de56255 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1860,7 +1860,7 @@ else if (Ustrncmp(name, "r_", 2) == 0)
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)
{
diff --git a/src/src/functions.h b/src/src/functions.h
index 92a4831e3..345d7bce6 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -447,6 +447,7 @@ extern BOOL regex_match_and_setup(const pcre2_code *, const uschar *, int, in
extern const pcre2_code *regex_compile(const uschar *, mcs_flags, uschar **,
pcre2_compile_context *);
extern const pcre2_code *regex_must_compile(const uschar *, mcs_flags, 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 **);
diff --git a/src/src/globals.c b/src/src/globals.c
index 574ee60a4..cafb15992 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -1324,7 +1324,7 @@ const pcre2_code *regex_EARLY_PIPE = NULL;
int regex_cachesize = 0;
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
diff --git a/src/src/regex.c b/src/src/regex.c
index 5de1c1704..25496f950 100644
--- a/src/src/regex.c
+++ b/src/src/regex.c
@@ -93,19 +93,27 @@ 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, BOOL cacheable)
+regex(const uschar ** listptr, BOOL cacheable)
{
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 */
{
@@ -167,14 +175,13 @@ return ret;
int
mime_regex(const uschar **listptr, BOOL cacheable)
{
-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, cacheable)))
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 11e7436b9..a15280bdc 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -2157,8 +2157,10 @@ prdr_requested = FALSE;
#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. */
diff --git a/test/confs/4002 b/test/confs/4002
index d9a12a368..4578cc019 100644
--- a/test/confs/4002
+++ b/test/confs/4002
@@ -10,6 +10,7 @@ rfc1413_query_timeout = 0s
acl_smtp_rcpt = check_rcpt
acl_smtp_data = check_data
+acl_smtp_mime = check_mime
acl_not_smtp = check_data
@@ -20,6 +21,15 @@ begin acl
check_rcpt:
accept
+check_mime:
+ warn condition = ${if match{$mime_content_type}{text}}
+ mime_regex = \N(?s)([\w.+=-]+@\w[\w-]*\.[\w.-]+\w)\
+ (.+?([\w.+=-]+@\w[\w-]*\.[\w.-]+\w))?\
+ (.+?([\w.+=-]+@\w[\w-]*\.[\w.-]+\w))?\
+ (.+?([\w.+=-]+@\w[\w-]*\.[\w.-]+\w))?\
+ (.+?([\w.+=-]+@\w[\w-]*\.[\w.-]+\w))?\N
+ accept
+
check_data:
warn regex = \N(THIS\s((\w+)\s)?REGEX)\N
message = X-Regex: Regex matched <$regex1> <$regex3>
diff --git a/test/mail/4002.userx b/test/mail/4002.userx
index 6bc565c3f..8ec49da09 100644
--- a/test/mail/4002.userx
+++ b/test/mail/4002.userx
@@ -27,9 +27,16 @@ Subject: A real test message
Date: Tue, 2 Mar 1999 09:44:33 +0000
Message-ID: <41C2F849.3060203@projectile.test.ex>
FakeReject: test fakereject
+MIME-Version: 1.0
+Content-Type: text/plain
Sender: CALLER_NAME <CALLER@myhost.test.ex>
X-Regex: Regex matched <THIS gazornenplaz REGEX> <gazornenplaz>
OK, this should look like a genuine message, but
it will trip on THIS gazornenplaz REGEX.
+This checks proper release of variable used for mime_regex
+firstname@foobar.com
+secondname@blaz.com
+thirdname@blaz.com
+
diff --git a/test/scripts/4000-scanning/4002 b/test/scripts/4000-scanning/4002
index a660f6805..fcfae698b 100644
--- a/test/scripts/4000-scanning/4002
+++ b/test/scripts/4000-scanning/4002
@@ -30,9 +30,16 @@ Subject: A real test message
Date: Fri, 17 Dec 2004 16:13:04 +0100
Message-ID: <41C2F849.3060203@projectile.test.ex>
FakeReject: test fakereject
+MIME-Version: 1.0
+Content-Type: text/plain
OK, this should look like a genuine message, but
it will trip on THIS gazornenplaz REGEX.
+
+This checks proper release of variable used for mime_regex
+firstname@foobar.com
+secondname@blaz.com
+thirdname@blaz.com
.
quit
****