summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Pennock <phil+git@pennock-tech.com>2020-10-29 21:48:05 -0400
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2021-04-28 00:40:24 +0200
commit3a54fcd1e303bf1cc49beca7ceac35d7448860a9 (patch)
treea6e8d52d79d4208daac505a0085270edc38150a0
parenta6e1f69d82adcfd3caab8f228d96750dfddc8f07 (diff)
downloadexim4-3a54fcd1e303bf1cc49beca7ceac35d7448860a9.tar.gz
SECURITY: Avoid integer overflow on too many recipients
(cherry picked from commit 323ff55e67b44e95f9d3cfaba155e385aa33c4bd)
-rw-r--r--doc/doc-txt/ChangeLog5
-rw-r--r--src/src/receive.c7
2 files changed, 12 insertions, 0 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 055b1ace8..3bb5326ce 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -191,6 +191,11 @@ PP/07 Refuse to allocate too little memory, block negative/zero allocations.
PP/08 Change default for recipients_max from unlimited to 50,000.
+PP/09 Fix security issue with too many recipients on a message (to remove a
+ known security problem if someone does set recipients_max to unlimited,
+ or if local additions add to the recipient list).
+ Fixes CVE-2020-RCPTL reported by Qualys.
+
Exim version 4.94
-----------------
diff --git a/src/src/receive.c b/src/src/receive.c
index ec90e93cd..ba6a8d3a6 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -485,11 +485,18 @@ Returns: nothing
void
receive_add_recipient(uschar *recipient, int pno)
{
+/* XXX This is a math limit; we should consider a performance/sanity limit too. */
+const int safe_recipients_limit = INT_MAX / sizeof(recipient_item) - 1;
+
if (recipients_count >= recipients_list_max)
{
recipient_item *oldlist = recipients_list;
int oldmax = recipients_list_max;
recipients_list_max = recipients_list_max ? 2*recipients_list_max : 50;
+ if ((recipients_list_max >= safe_recipients_limit) || (recipients_list_max < 0))
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC, "Too many recipients needed: %d not satisfiable", recipients_list_max);
+ }
recipients_list = store_get(recipients_list_max * sizeof(recipient_item), FALSE);
if (oldlist != NULL)
memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item));