1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-12-22 04:17:44 +00:00

mail/exim: attempt to fix *taint* and auth issues

Bump PORTREVISION for master port to force all slaves rebuild
Drop PORTREVISION for exim-postgresql slave in favor of master settings

Adopt recent commits from Exim repo as numerated extra-patches till new maintenance release will be published:

19. SPF: fix result for case of only non-spf TXT RRs
20. Fix error logging for dynamically-loaded modules
21. heimdal auth: fix the increase of big_buffer size
22. Taint: hybrid checking mode
23. Fix taint hybrid-checking on BSD
24. TFO: even in binary built for modern Linux, handle error returned by old Linux kernel
25. Taint: slow-mode checking only
26. Auths: fix cyrus-sasl driver for gssapi use
27. GnuTLS: fix hanging callout connections
This commit is contained in:
Dima Panov 2020-02-26 13:46:15 +00:00
parent 3fdf2a763e
commit 48f0116002
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=527168
11 changed files with 952 additions and 1 deletions

View File

@ -1,7 +1,6 @@
# Created by: Sheldon Hearn <sheldonh@FreeBSD.org>
# $FreeBSD$
PORTREVISION= 2
PKGNAMESUFFIX= -postgresql
MASTERDIR= ${.CURDIR}/../exim

View File

@ -3,6 +3,7 @@
PORTNAME= exim
PORTVERSION?= ${EXIM_VERSION}
PORTREVISION?= 3
CATEGORIES= mail
MASTER_SITES= EXIM:exim
MASTER_SITE_SUBDIR= /exim4/:exim \
@ -105,6 +106,7 @@ EXTRA_PATCHES+= ${FILESDIR}/extra-patch-Local-sa-exim.conf
EXIM_VERSION= 4.93.0.4
SA_EXIM_VERSION=4.2.1
EXIM_INSTALL_ARG+= "-no_chown" "-no_symlink"
EXTRA_PATCHES+= `${FIND} ${PATCHDIR} -name '74_*.patch'`
.if !defined(EXIMON_ONLY)
PLIST_SUB+= EXIM=""

View File

@ -0,0 +1,34 @@
From dfb8f72b2237627b26767d1e803e8ed95ad659d2 Mon Sep 17 00:00:00 2001
From: Wolfgang Breyha <wbreyha@gmx.net>
Date: Tue, 7 Jan 2020 13:03:18 +0000
Subject: [PATCH 19/21] SPF: fix result for case of only non-spf TXT RRs. Bug
2499
(cherry picked from commit 67794d2b830fc580f87b0635718d95e32b467be1)
---
src/spf.c | 7 ++++++-
test/scripts/4600-SPF/4601 | 17 ++++++++---------
test/stdout/4601 | 11 ++++++-----
3 files changed, 20 insertions(+), 15 deletions(-)
diff --git src/spf.c src/spf.c
index 8ead817b9..12b756b46 100644
--- src/spf.c
+++ src/spf.c
@@ -139,7 +139,12 @@ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
srr.rr[found++] = (void *) s;
}
-srr.num_rr = found;
+/* Did we filter out all TXT RRs? Return NO_DATA instead of SUCCESS with
+empty ANSWER section. */
+
+if (!(srr.num_rr = found))
+ srr.herrno = NO_DATA;
+
/* spfrr->rr must have been malloc()d for this */
SPF_dns_rr_dup(&spfrr, &srr);
return spfrr;
--
2.24.1

View File

@ -0,0 +1,70 @@
From 338f36842f10ef84e684dddf59819837fd7792a3 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Wed, 15 Jan 2020 10:40:20 +0000
Subject: [PATCH 20/21] Fix error logging for dynamically-loaded modules. Bug
2507
(cherry picked from commits b1c673ddfa, 3fc07bd570)
---
doc/ChangeLog | 5 +++++
src/drtables.c | 13 +++++++------
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index 32febe1f3..6e26e2f11 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -49,6 +49,11 @@ JH/16 Fix the variables set by the gsasl authenticator. Previously a pointer to
library live data was being used, so the results became garbage. Make
copies while it is still usable.
+JH/19 Bug 2507: Modules: on handling a dynamic-module (lookups) open failure,
+ only retrieve the errormessage once. Previously two calls to dlerror()
+ were used, and the second one (for mainlog/paniclog) retrieved null
+ information.
+
Exim version 4.93
-----------------
diff --git src/drtables.c src/drtables.c
index 059756284..ca051bd20 100644
--- src/drtables.c
+++ src/drtables.c
@@ -740,10 +740,11 @@ init_lookup_list(void)
dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
if (dl == NULL) {
- fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
- moduleerrors++;
- log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
- continue;
+ errormessage = dlerror();
+ fprintf(stderr, "Error loading %s: %s\n", name, errormessage);
+ log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormessage);
+ moduleerrors++;
+ continue;
}
/* FreeBSD nsdispatch() can trigger dlerror() errors about
@@ -756,16 +757,16 @@ init_lookup_list(void)
info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
if ((errormsg = dlerror()) != NULL) {
fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
+ log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
dlclose(dl);
moduleerrors++;
- log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
continue;
}
if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
+ log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
dlclose(dl);
moduleerrors++;
- log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
continue;
}
--
2.24.1

View File

@ -0,0 +1,116 @@
From bbeab68df3b3c2d5507b1fdca07509fdbb3ec5a1 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Tue, 14 Jan 2020 17:48:57 +0000
Subject: [PATCH 21/21] heimdal auth: fix the increase of big_buffer size. Bug
2501
(cherry picked from commit 7a66b3afa11a70021297c176acf56831692be89a)
---
doc/ChangeLog | 7 ++++++-
src/auths/README | 2 +-
src/auths/heimdal_gssapi.c | 10 ----------
src/macros.h | 13 ++++++++++---
src/readconf.c | 1 +
5 files changed, 18 insertions(+), 15 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index 6e26e2f11..f112fc9bf 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -9,7 +9,7 @@ This is not an official release. It is just a branch, collecting
proposed bugfixes. Depending on your environment the fixes may be
necessary to build and/or run Exim successfully.
-JH/05 Regard command-line receipients as tainted.
+JH/05 Regard command-line recipients as tainted.
JH/07 Bug 2489: Fix crash in the "pam" expansion condition. It seems that the
PAM library frees one of the arguments given to it, despite the
@@ -54,6 +54,11 @@ JH/19 Bug 2507: Modules: on handling a dynamic-module (lookups) open failure,
were used, and the second one (for mainlog/paniclog) retrieved null
information.
+JH/21 Bug 2501: Fix init call in the heimdal authenticator. Previously it
+ adjusted the size of a major service buffer; this failed because the
+ buffer was in use at the time. Change to a compile-time increase in the
+ buffer size, when this authenticator is compiled into exim.
+
Exim version 4.93
-----------------
diff --git src/auths/README src/auths/README
index d4f125c30..66bdcdcf8 100644
--- src/auths/README
+++ src/auths/README
@@ -34,7 +34,7 @@ instance block for this configured mechanism. It must set the flags called
the server and/or client functions are available for this authenticator.
Typically this depends on whether server or client configuration options have
been set, but it is also possible to have an authenticator that has only one of
-the server or client functions.
+the server or client functions. The function may not touch big_buffer.
SERVER AUTHENTICATION
diff --git src/auths/heimdal_gssapi.c src/auths/heimdal_gssapi.c
index 3dfcb8c6a..523f7c69a 100644
--- src/auths/heimdal_gssapi.c
+++ src/auths/heimdal_gssapi.c
@@ -200,16 +200,6 @@ if (krc)
krb5_free_context(context);
-/* RFC 4121 section 5.2, SHOULD support 64K input buffers */
-if (big_buffer_size < (64 * 1024))
- {
- uschar *newbuf;
- big_buffer_size = 64 * 1024;
- newbuf = store_malloc(big_buffer_size);
- store_free(big_buffer);
- big_buffer = newbuf;
- }
-
ablock->server = TRUE;
}
diff --git src/macros.h src/macros.h
index 76913d64e..4e6b1b8a9 100644
--- src/macros.h
+++ src/macros.h
@@ -152,12 +152,19 @@ enough to hold all the headers from a normal kind of message. */
into big_buffer_size and in some circumstances increased. It should be at least
as long as the maximum path length. */
-#if defined PATH_MAX && PATH_MAX > 16384
+#ifdef AUTH_HEIMDAL_GSSAPI
+ /* RFC 4121 section 5.2, SHOULD support 64K input buffers */
+# define __BIG_BUFFER_SIZE 65536
+#else
+# define __BIG_BUFFER_SIZE 16384
+#endif
+
+#if defined PATH_MAX && PATH_MAX > __BIG_BUFFER_SIZE
# define BIG_BUFFER_SIZE PATH_MAX
-#elif defined MAXPATHLEN && MAXPATHLEN > 16384
+#elif defined MAXPATHLEN && MAXPATHLEN > __BIG_BUFFER_SIZE
# define BIG_BUFFER_SIZE MAXPATHLEN
#else
-# define BIG_BUFFER_SIZE 16384
+# define BIG_BUFFER_SIZE __BIG_BUFFER_SIZE
#endif
/* header size of pipe content
diff --git src/readconf.c src/readconf.c
index 0233019cf..62cfcfbf9 100644
--- src/readconf.c
+++ src/readconf.c
@@ -3788,6 +3788,7 @@ while ((buffer = get_config_line()) != NULL)
if (!d->driver_name)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
"no driver defined for %s \"%s\"", class, d->name);
+ /* s is using big_buffer, so this call had better not */
(d->info->init)(d);
d = NULL;
}
--
2.24.1

View File

@ -0,0 +1,330 @@
From 1ccd26e24267ffa0c40b70c2c3282481fe4977c7 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Thu, 16 Jan 2020 14:12:56 +0000
Subject: [PATCH 22/22] Taint: hybrid checking mode
(cherry picked from commit 36eb5d3d77426d8cbf4243ea752f8d8cd1d5c682)
---
doc/ChangeLog | 8 +++++
exim_monitor/em_version.c | 2 ++
src/functions.h | 58 +++++++++++++++++++++++++++++++-
src/globals.c | 1 +
src/globals.h | 1 +
src/mytypes.h | 62 +++++------------------------------
src/store.c | 40 +++++++++++++++-------
7 files changed, 107 insertions(+), 65 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index f112fc9bf..508b8fa49 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -59,6 +59,14 @@ JH/21 Bug 2501: Fix init call in the heimdal authenticator. Previously it
buffer was in use at the time. Change to a compile-time increase in the
buffer size, when this authenticator is compiled into exim.
+JH/22 Taint checking: move to a hybrid approach for checking. Previously, one
+ of two ways was used, depending on a build-time flag. The fast method
+ relied on assumptions about the OS and libc malloc, which were known to
+ not hold for the BSD-derived platforms, and discovered to not hold for
+ 32-bit Linux either. In fact the glibc documentation describes cases
+ where these assumptions do not hold. The new implementation tests for
+ the situation arising and actively switches over from fast to safe mode.
+
Exim version 4.93
-----------------
diff --git exim_monitor/em_version.c exim_monitor/em_version.c
index 52c55a4a3..9b9c7d417 100644
--- exim_monitor/em_version.c
+++ exim_monitor/em_version.c
@@ -5,6 +5,8 @@
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
+#define EM_VERSION_C
+
#include "mytypes.h"
#include "store.h"
#include "macros.h"
diff --git src/functions.h src/functions.h
index 87d1a04d8..0b5905562 100644
--- src/functions.h
+++ src/functions.h
@@ -187,6 +187,7 @@ extern void deliver_succeeded(address_item *);
extern uschar *deliver_get_sender_address (uschar *id);
extern void delivery_re_exec(int);
+extern void die_tainted(const uschar *, const uschar *, int);
extern BOOL directory_make(const uschar *, const uschar *, int, BOOL);
#ifndef DISABLE_DKIM
extern uschar *dkim_exim_query_dns_txt(const uschar *);
@@ -602,6 +603,61 @@ extern BOOL write_chunk(transport_ctx *, uschar *, int);
extern ssize_t write_to_fd_buf(int, const uschar *, size_t);
+/******************************************************************************/
+/* Predicate: if an address is in a tainted pool.
+By extension, a variable pointing to this address is tainted.
+*/
+
+static inline BOOL
+is_tainted(const void * p)
+{
+#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) || defined(EM_VERSION_C)
+return FALSE;
+
+#else
+extern BOOL is_tainted_fn(const void *);
+extern void * tainted_base, * tainted_top;
+
+return f.taint_check_slow
+ ? is_tainted_fn(p) : p >= tainted_base && p < tainted_top;
+#endif
+}
+
+/******************************************************************************/
+/* String functions */
+static inline uschar * __Ustrcat(uschar * dst, const uschar * src, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line);
+#endif
+return US strcat(CS dst, CCS src);
+}
+static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line);
+#endif
+return US strcpy(CS dst, CCS src);
+}
+static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line);
+#endif
+return US strncat(CS dst, CCS src, n);
+}
+static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line);
+#endif
+return US strncpy(CS dst, CCS src, n);
+}
+/*XXX will likely need unchecked copy also */
+
+
+/******************************************************************************/
+
#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
/* exim_chown - in some NFSv4 setups *seemes* to be an issue with
chown(<exim-uid>, <exim-gid>).
@@ -634,8 +690,8 @@ exim_chown(const uschar *name, uid_t owner, gid_t group)
return chown(CCS name, owner, group)
? exim_chown_failure(-1, name, owner, group) : 0;
}
-
#endif /* !MACRO_PREDEF && !COMPILE_UTILITY */
+
/******************************************************************************/
/* String functions */
diff --git src/globals.c src/globals.c
index 85a25a7f2..72449229e 100644
--- src/globals.c
+++ src/globals.c
@@ -311,6 +311,7 @@ struct global_flags f =
.synchronous_delivery = FALSE,
.system_filtering = FALSE,
+ .taint_check_slow = FALSE,
.tcp_fastopen_ok = FALSE,
.tcp_in_fastopen = FALSE,
.tcp_in_fastopen_data = FALSE,
diff --git src/globals.h src/globals.h
index ca342acc2..ac7bb8ef3 100644
--- src/globals.h
+++ src/globals.h
@@ -272,6 +272,7 @@ extern struct global_flags {
BOOL synchronous_delivery :1; /* TRUE if -odi is set */
BOOL system_filtering :1; /* TRUE when running system filter */
+ BOOL taint_check_slow :1; /* malloc/mmap are not returning distinct ranges */
BOOL tcp_fastopen_ok :1; /* appears to be supported by kernel */
BOOL tcp_in_fastopen :1; /* conn usefully used fastopen */
BOOL tcp_in_fastopen_data :1; /* fastopen carried data */
diff --git src/mytypes.h src/mytypes.h
index ceb9f1b55..e31ee8c1a 100644
--- src/mytypes.h
+++ src/mytypes.h
@@ -100,19 +100,15 @@ functions that are called quite often; for other calls to external libraries
#define Uread(f,b,l) read(f,CS(b),l)
#define Urename(s,t) rename(CCS(s),CCS(t))
#define Ustat(s,t) stat(CCS(s),t)
-#define Ustrcat(s,t) __Ustrcat(s, CUS(t), __FUNCTION__, __LINE__)
#define Ustrchr(s,n) US strchr(CCS(s),n)
#define CUstrchr(s,n) CUS strchr(CCS(s),n)
#define CUstrerror(n) CUS strerror(n)
#define Ustrcmp(s,t) strcmp(CCS(s),CCS(t))
-#define Ustrcpy(s,t) __Ustrcpy(s, CUS(t), __FUNCTION__, __LINE__)
#define Ustrcpy_nt(s,t) strcpy(CS s, CCS t) /* no taint check */
#define Ustrcspn(s,t) strcspn(CCS(s),CCS(t))
#define Ustrftime(s,m,f,t) strftime(CS(s),m,f,t)
#define Ustrlen(s) (int)strlen(CCS(s))
-#define Ustrncat(s,t,n) __Ustrncat(s, CUS(t),n, __FUNCTION__, __LINE__)
#define Ustrncmp(s,t,n) strncmp(CCS(s),CCS(t),n)
-#define Ustrncpy(s,t,n) __Ustrncpy(s, CUS(t),n, __FUNCTION__, __LINE__)
#define Ustrncpy_nt(s,t,n) strncpy(CS s, CCS t, n) /* no taint check */
#define Ustrpbrk(s,t) strpbrk(CCS(s),CCS(t))
#define Ustrrchr(s,n) US strrchr(CCS(s),n)
@@ -125,57 +121,17 @@ functions that are called quite often; for other calls to external libraries
#define Ustrtoul(s,t,b) strtoul(CCS(s),CSS(t),b)
#define Uunlink(s) unlink(CCS(s))
-extern void die_tainted(const uschar *, const uschar *, int);
-
-/* Predicate: if an address is in a tainted pool.
-By extension, a variable pointing to this address is tainted.
-*/
-
-static inline BOOL
-is_tainted(const void * p)
-{
-#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF)
-return FALSE;
-
-#elif defined(TAINT_CHECK_SLOW)
-extern BOOL is_tainted_fn(const void *);
-return is_tainted_fn(p);
-
+#ifdef EM_VERSION_C
+# define Ustrcat(s,t) strcat(CS(s), CCS(t))
+# define Ustrcpy(s,t) strcpy(CS(s), CCS(t))
+# define Ustrncat(s,t,n) strncat(CS(s), CCS(t), n)
+# define Ustrncpy(s,t,n) strncpy(CS(s), CCS(t), n)
#else
-extern void * tainted_base, * tainted_top;
-return p >= tainted_base && p < tainted_top;
-#endif
-}
-
-static inline uschar * __Ustrcat(uschar * dst, const uschar * src, const char * func, int line)
-{
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line);
-#endif
-return US strcat(CS dst, CCS src);
-}
-static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line)
-{
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line);
-#endif
-return US strcpy(CS dst, CCS src);
-}
-static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line)
-{
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line);
-#endif
-return US strncat(CS dst, CCS src, n);
-}
-static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line)
-{
-#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
-if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line);
+# define Ustrcat(s,t) __Ustrcat(s, CUS(t), __FUNCTION__, __LINE__)
+# define Ustrcpy(s,t) __Ustrcpy(s, CUS(t), __FUNCTION__, __LINE__)
+# define Ustrncat(s,t,n) __Ustrncat(s, CUS(t), n, __FUNCTION__, __LINE__)
+# define Ustrncpy(s,t,n) __Ustrncpy(s, CUS(t), n, __FUNCTION__, __LINE__)
#endif
-return US strncpy(CS dst, CCS src, n);
-}
-/*XXX will likely need unchecked copy also */
#endif
/* End of mytypes.h */
diff --git src/store.c src/store.c
index a06e1c19a..692a993e9 100644
--- src/store.c
+++ src/store.c
@@ -162,8 +162,14 @@ static void internal_tainted_free(storeblock *, const char *, int linenumber);
/******************************************************************************/
-/* Slower version check, for use when platform intermixes malloc and mmap area
-addresses. */
+/* Test if a pointer refers to tainted memory.
+
+Slower version check, for use when platform intermixes malloc and mmap area
+addresses. Test against the current-block of all tainted pools first, then all
+blocks of all tainted pools.
+
+Return: TRUE iff tainted
+*/
BOOL
is_tainted_fn(const void * p)
@@ -171,23 +177,20 @@ is_tainted_fn(const void * p)
storeblock * b;
int pool;
-for (pool = 0; pool < nelem(chainbase); pool++)
+for (pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
if ((b = current_block[pool]))
{
- char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK;
- if (CS p >= bc && CS p <= bc + b->length) goto hit;
+ uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
+ if (US p >= bc && US p <= bc + b->length) return TRUE;
}
-for (pool = 0; pool < nelem(chainbase); pool++)
+for (pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
for (b = chainbase[pool]; b; b = b->next)
{
- char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK;
- if (CS p >= bc && CS p <= bc + b->length) goto hit;
+ uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
+ if (US p >= bc && US p <= bc + b->length) return TRUE;
}
return FALSE;
-
-hit:
-return pool >= POOL_TAINT_BASE;
}
@@ -198,6 +201,13 @@ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Taint mismatch, %s: %s %d\n",
msg, func, line);
}
+static void
+use_slow_taint_check(void)
+{
+DEBUG(D_any) debug_printf("switching to slow-mode taint checking\n");
+f.taint_check_slow = TRUE;
+}
+
/*************************************************
* Get a block from the current pool *
@@ -820,6 +830,14 @@ if (!(yield = malloc((size_t)size)))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to malloc %d bytes of memory: "
"called from line %d in %s", size, linenumber, func);
+/* If malloc ever returns apparently tainted memory, which glibc
+malloc will as it uses mmap for larger requests, we must switch to
+the slower checking for tainting (checking an address against all
+the tainted pool block spans, rather than just the mmap span) */
+
+if (!f.taint_check_slow && is_tainted(yield))
+ use_slow_taint_check();
+
return store_alloc_tail(yield, size, func, linenumber, US"Malloc");
}
--
2.24.1

View File

@ -0,0 +1,83 @@
From ccf4e2396b27b519174aa79552e61d11aafbdc36 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Fri, 17 Jan 2020 21:55:11 +0000
Subject: [PATCH 23/23] Fix taint hybrid-checking on BSD
(cherry-picked from commit 677481d4fc)
Broken-by: 1ccd26e242
---
src/store.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git src/store.c src/store.c
index 692a993e9..6118ef28d 100644
--- src/store.c
+++ src/store.c
@@ -175,16 +175,15 @@ BOOL
is_tainted_fn(const void * p)
{
storeblock * b;
-int pool;
-for (pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
+for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
if ((b = current_block[pool]))
{
uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
if (US p >= bc && US p <= bc + b->length) return TRUE;
}
-for (pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
+for (int pool = POOL_TAINT_BASE; pool < nelem(chainbase); pool++)
for (b = chainbase[pool]; b; b = b->next)
{
uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
@@ -204,10 +203,28 @@ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Taint mismatch, %s: %s %d\n",
static void
use_slow_taint_check(void)
{
+#ifndef COMPILE_UTILITY
DEBUG(D_any) debug_printf("switching to slow-mode taint checking\n");
+#endif
f.taint_check_slow = TRUE;
}
+static void
+verify_all_untainted(void)
+{
+for (int pool = 0; pool < POOL_TAINT_BASE; pool++)
+ for (storeblock * b = chainbase[pool]; b; b = b->next)
+ {
+ uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
+ if (is_tainted(bc))
+ {
+ use_slow_taint_check();
+ return;
+ }
+ }
+}
+
+
/*************************************************
* Get a block from the current pool *
@@ -740,7 +757,7 @@ int pool = tainted ? store_pool + POOL_TAINT_BASE : store_pool;
BOOL release_ok = !tainted && store_last_get[pool] == block;
uschar * newtext;
-#ifndef MACRO_PREDEF
+#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
if (is_tainted(block) != tainted)
die_tainted(US"store_newblock", CUS func, linenumber);
#endif
@@ -799,6 +816,7 @@ if (!(yield = mmap(NULL, (size_t)size,
if (yield < tainted_base) tainted_base = yield;
if ((top = US yield + size) > tainted_top) tainted_top = top;
+if (!f.taint_check_slow) use_slow_taint_check();
return store_alloc_tail(yield, size, func, line, US"Mmap");
}
--
2.24.1

View File

@ -0,0 +1,70 @@
From 4ce411ffa737df738e18e1e7b008ad3d3ac5c398 Mon Sep 17 00:00:00 2001
From: Brian Foley <bpfoley@google.com>
Date: Sat, 25 Jan 2020 15:27:49 +0000
Subject: [PATCH 24/25] TFO: even in binary built for modern Linux, handle
error returned by old Linux kernel. Bug 2518
(cherry picked from commit c3da38a12a2372a7f6a48be97ebfd80aeceda828)
---
src/ip.c | 40 +++++++++++++++++++++++-----------------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git src/ip.c src/ip.c
index 70e3e2064..43ca6a1c9 100644
--- src/ip.c
+++ src/ip.c
@@ -269,28 +269,34 @@ if (fastopen_blob && f.tcp_fastopen_ok)
/*XXX also seen on successful TFO, sigh */
tcp_out_fastopen = fastopen_blob->len > 0 ? TFO_ATTEMPTED_DATA : TFO_ATTEMPTED_NODATA;
}
- else if (errno == EINPROGRESS) /* expected if we had no cookie for peer */
+ else switch (errno)
+ {
+ case EINPROGRESS: /* expected if we had no cookie for peer */
/* seen for no-data, proper TFO option, both cookie-request and with-cookie cases */
/* apparently no visibility of the diffference at this point */
/* seen for with-data, proper TFO opt, cookie-req */
/* with netwk delay, post-conn tcp_info sees unacked 1 for R, 2 for C; code in smtp_out.c */
/* ? older Experimental TFO option behaviour ? */
- { /* queue unsent data */
- DEBUG(D_transport|D_v) debug_printf(" TFO mode sendto, %s data: EINPROGRESS\n",
- fastopen_blob->len > 0 ? "with" : "no");
- if (!fastopen_blob->data)
- {
- tcp_out_fastopen = TFO_ATTEMPTED_NODATA; /* we tried; unknown if useful yet */
- rc = 0;
- }
- else
- rc = send(sock, fastopen_blob->data, fastopen_blob->len, 0);
- }
- else if(errno == EOPNOTSUPP)
- {
- DEBUG(D_transport)
- debug_printf("Tried TCP Fast Open but apparently not enabled by sysctl\n");
- goto legacy_connect;
+ DEBUG(D_transport|D_v) debug_printf(" TFO mode sendto, %s data: EINPROGRESS\n",
+ fastopen_blob->len > 0 ? "with" : "no");
+ if (!fastopen_blob->data)
+ {
+ tcp_out_fastopen = TFO_ATTEMPTED_NODATA; /* we tried; unknown if useful yet */
+ rc = 0;
+ }
+ else /* queue unsent data */
+ rc = send(sock, fastopen_blob->data, fastopen_blob->len, 0);
+ break;
+
+ case EOPNOTSUPP:
+ DEBUG(D_transport)
+ debug_printf("Tried TCP Fast Open but apparently not enabled by sysctl\n");
+ goto legacy_connect;
+
+ case EPIPE:
+ DEBUG(D_transport)
+ debug_printf("Tried TCP Fast Open but kernel too old to support it\n");
+ goto legacy_connect;
}
# endif
# ifdef EXIM_TFO_CONNECTX
--
2.24.1

View File

@ -0,0 +1,127 @@
From 69b2f92c0b5da548eaafe4813319f4647fa9c19a Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Thu, 30 Jan 2020 11:38:30 +0000
Subject: [PATCH 25/25] Taint: slow-mode checking only
(cherry-picked from 4381d60bc9)
---
doc/ChangeLog | 10 +++-------
src/functions.h | 5 +----
src/store.c | 43 -------------------------------------------
3 files changed, 4 insertions(+), 54 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index 508b8fa49..be7ec2a8e 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -59,13 +59,9 @@ JH/21 Bug 2501: Fix init call in the heimdal authenticator. Previously it
buffer was in use at the time. Change to a compile-time increase in the
buffer size, when this authenticator is compiled into exim.
-JH/22 Taint checking: move to a hybrid approach for checking. Previously, one
- of two ways was used, depending on a build-time flag. The fast method
- relied on assumptions about the OS and libc malloc, which were known to
- not hold for the BSD-derived platforms, and discovered to not hold for
- 32-bit Linux either. In fact the glibc documentation describes cases
- where these assumptions do not hold. The new implementation tests for
- the situation arising and actively switches over from fast to safe mode.
+JH/22 Taint-checking: move to safe-mode taint checking on all platforms. The
+ previous fast-mode was untenable in the face of glibs using mmap to
+ support larger malloc requests.
Exim version 4.93
diff --git src/functions.h src/functions.h
index 0b5905562..af633851b 100644
--- src/functions.h
+++ src/functions.h
@@ -616,10 +616,7 @@ return FALSE;
#else
extern BOOL is_tainted_fn(const void *);
-extern void * tainted_base, * tainted_top;
-
-return f.taint_check_slow
- ? is_tainted_fn(p) : p >= tainted_base && p < tainted_top;
+return is_tainted_fn(p);
#endif
}
diff --git src/store.c src/store.c
index 6118ef28d..c81744a7b 100644
--- src/store.c
+++ src/store.c
@@ -102,13 +102,6 @@ static storeblock *current_block[NPOOLS];
static void *next_yield[NPOOLS];
static int yield_length[NPOOLS] = { -1, -1, -1, -1, -1, -1 };
-/* The limits of the tainted pools. Tracking these on new allocations enables
-a fast is_tainted implementation. We assume the kernel only allocates mmaps using
-one side or the other of data+heap, not both. */
-
-void * tainted_base = (void *)-1;
-void * tainted_top = (void *)0;
-
/* pool_malloc holds the amount of memory used by the store pools; this goes up
and down as store is reset or released. nonpool_malloc is the total got by
malloc from other calls; this doesn't go down because it is just freed by
@@ -200,30 +193,6 @@ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Taint mismatch, %s: %s %d\n",
msg, func, line);
}
-static void
-use_slow_taint_check(void)
-{
-#ifndef COMPILE_UTILITY
-DEBUG(D_any) debug_printf("switching to slow-mode taint checking\n");
-#endif
-f.taint_check_slow = TRUE;
-}
-
-static void
-verify_all_untainted(void)
-{
-for (int pool = 0; pool < POOL_TAINT_BASE; pool++)
- for (storeblock * b = chainbase[pool]; b; b = b->next)
- {
- uschar * bc = US b + ALIGNED_SIZEOF_STOREBLOCK;
- if (is_tainted(bc))
- {
- use_slow_taint_check();
- return;
- }
- }
-}
-
/*************************************************
@@ -814,10 +783,6 @@ if (!(yield = mmap(NULL, (size_t)size,
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to mmap %d bytes of memory: "
"called from line %d of %s", size, line, func);
-if (yield < tainted_base) tainted_base = yield;
-if ((top = US yield + size) > tainted_top) tainted_top = top;
-if (!f.taint_check_slow) use_slow_taint_check();
-
return store_alloc_tail(yield, size, func, line, US"Mmap");
}
@@ -848,14 +813,6 @@ if (!(yield = malloc((size_t)size)))
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to malloc %d bytes of memory: "
"called from line %d in %s", size, linenumber, func);
-/* If malloc ever returns apparently tainted memory, which glibc
-malloc will as it uses mmap for larger requests, we must switch to
-the slower checking for tainting (checking an address against all
-the tainted pool block spans, rather than just the mmap span) */
-
-if (!f.taint_check_slow && is_tainted(yield))
- use_slow_taint_check();
-
return store_alloc_tail(yield, size, func, linenumber, US"Malloc");
}
--
2.24.1

View File

@ -0,0 +1,50 @@
From 59bcc75f56ffeb9fa220f1eb53d45bf254258ac7 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Thu, 13 Feb 2020 14:08:31 +0000
Subject: [PATCH 26/27] Auths: fix cyrus-sasl driver for gssapi use. Bug 2524
Broken-by: c0fb53b74e
Cherry-picked from: 5c329a4388
---
doc/ChangeLog | 6 ++++++
src/auths/cyrus_sasl.c | 6 +++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index be7ec2a8e..97fe878dc 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -63,6 +63,12 @@ JH/22 Taint-checking: move to safe-mode taint checking on all platforms. The
previous fast-mode was untenable in the face of glibs using mmap to
support larger malloc requests.
+JH/24 Bug 2524: fix the cyrus_sasl auth driver gssapi usage. A previous fix
+ had introduced a string-copy (for ensuring NUL-termination) which was not
+ appropriate for that case, which can include embedded NUL bytes in the
+ block of data. Investigation showed the copy to actually be needless, the
+ data being length-specified.
+
Exim version 4.93
-----------------
diff --git src/auths/cyrus_sasl.c src/auths/cyrus_sasl.c
index 480010bab..19416a1bb 100644
--- src/auths/cyrus_sasl.c
+++ src/auths/cyrus_sasl.c
@@ -347,10 +347,10 @@ for (rc = SASL_CONTINUE; rc == SASL_CONTINUE; )
}
else
{
- /* make sure that we have a null-terminated string */
- out2 = string_copyn(output, outlen);
+ /* auth_get_data() takes a length-specfied block of binary
+ which can include zeroes; no terminating NUL is needed */
- if ((rc = auth_get_data(&input, out2, outlen)) != OK)
+ if ((rc = auth_get_data(&input, output, outlen)) != OK)
{
/* we couldn't get the data, so free up the library before
* returning whatever error we get */
--
2.24.1

View File

@ -0,0 +1,70 @@
From 26b045604bd574a6d93868ed437c08503c67d289 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Thu, 13 Feb 2020 16:52:52 +0000
Subject: [PATCH 27/27] GnuTLS: fix hanging callout connections
Broken-by: 925ac8e4f1
Cherry-picked from: bd95ffc2ba
---
doc/ChangeLog | 5 +++++
src/tls-gnu.c | 11 +++++++----
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git doc/ChangeLog doc/ChangeLog
index 97fe878dc..d9833c8e1 100644
--- doc/ChangeLog
+++ doc/ChangeLog
@@ -69,6 +69,11 @@ JH/24 Bug 2524: fix the cyrus_sasl auth driver gssapi usage. A previous fix
block of data. Investigation showed the copy to actually be needless, the
data being length-specified.
+JH/25 Fix use of concurrent TLS connections under GnuTLS. When a callout was
+ done during a receiving connection, and both used TLS, global info was
+ used rather than per-connection info for tracking the state of data
+ queued for transmission. This could result in a connection hang.
+
Exim version 4.93
-----------------
diff --git src/tls-gnu.c src/tls-gnu.c
index fc426a251..574dcafd9 100644
--- src/tls-gnu.c
+++ src/tls-gnu.c
@@ -181,6 +181,10 @@ typedef struct exim_gnutls_state {
BOOL peer_dane_verified;
BOOL trigger_sni_changes;
BOOL have_set_peerdn;
+#ifdef SUPPORT_CORK
+ BOOL corked:1;
+#endif
+
const struct host_item *host; /* NULL if server */
gnutls_x509_crt_t peercert;
uschar *peerdn;
@@ -3309,9 +3313,8 @@ ssize_t outbytes;
size_t left = len;
exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server;
#ifdef SUPPORT_CORK
-static BOOL corked = FALSE;
-if (more && !corked) gnutls_record_cork(state->session);
+if (more && !state->corked) gnutls_record_cork(state->session);
#endif
DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__,
@@ -3352,10 +3355,10 @@ if (len > INT_MAX)
}
#ifdef SUPPORT_CORK
-if (more != corked)
+if (more != state->corked)
{
if (!more) (void) gnutls_record_uncork(state->session, 0);
- corked = more;
+ state->corked = more;
}
#endif
--
2.24.1