summaryrefslogtreecommitdiffstats
path: root/debian/patches/75_08-Fix-regex-n-use-after-free.-Bug-2915.patch
blob: be6ccae0227c5354c52daae02e07c160108a5bd5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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

---
 doc/ChangeLog           |  8 +++++++-
 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 +++++++
 10 files changed, 55 insertions(+), 17 deletions(-)

--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -4,15 +4,21 @@
 
 JH/04 Bug 2903: avoid exit on an attempt to rewrite a malformed address.
       Make the rewrite never match and keep the logging.  Trust the
       admin to be using verify=header-syntax (to actually reject the message).
 
+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.
 
 JH/02 Move from using the pcre library to pcre2.  The former is no longer
--- 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 */