commit 00b35aee4cdc8a002b537d51585f925aba19db09
Author: Fabian Groffen <grobian@gentoo.org>
Date:   Tue Dec 10 17:32:12 2019 +0000

    PAM: fix crash in the pam expansion condition.  Bug 2489
    
    Broken-by: f3ebb786e4
    (cherry picked from commit dcbfbadac2f557dc73bbcf2b26aadf50f8414ca1)

diff --git a/src/src/auths/call_pam.c b/src/src/auths/call_pam.c
index 9a46b6b63..c96e146d1 100644
--- a/src/src/auths/call_pam.c
+++ b/src/src/auths/call_pam.c
@@ -69,9 +69,11 @@ pam_converse (int num_msg, PAM_CONVERSE_ARG2_TYPE **msg,
 int sep = 0;
 struct pam_response *reply;
 
-if (pam_arg_ended) return PAM_CONV_ERR;
+/* It seems that PAM frees reply[] */
 
-reply = store_get(sizeof(struct pam_response) * num_msg, FALSE);
+if (  pam_arg_ended
+   || !(reply = malloc(sizeof(struct pam_response) * num_msg)))
+  return PAM_CONV_ERR;
 
 for (int i = 0; i < num_msg; i++)
   {
@@ -80,25 +82,26 @@ for (int i = 0; i < num_msg; i++)
     {
     case PAM_PROMPT_ECHO_ON:
     case PAM_PROMPT_ECHO_OFF:
-    arg = string_nextinlist(&pam_args, &sep, big_buffer, big_buffer_size);
-    if (arg == NULL)
-      {
-      arg = US"";
-      pam_arg_ended = TRUE;
-      }
-    reply[i].resp = CS string_copy_perm(arg, FALSE); /* PAM frees resp */
-    reply[i].resp_retcode = PAM_SUCCESS;
-    break;
+      arg = string_nextinlist(&pam_args, &sep, big_buffer, big_buffer_size);
+      if (!arg)
+	{
+	arg = US"";
+	pam_arg_ended = TRUE;
+	}
+      reply[i].resp = CS string_copy_malloc(arg); /* PAM frees resp */
+      reply[i].resp_retcode = PAM_SUCCESS;
+      break;
 
     case PAM_TEXT_INFO:    /* Just acknowledge messages */
     case PAM_ERROR_MSG:
-    reply[i].resp_retcode = PAM_SUCCESS;
-    reply[i].resp = NULL;
-    break;
+      reply[i].resp_retcode = PAM_SUCCESS;
+      reply[i].resp = NULL;
+      break;
 
     default:  /* Must be an error of some sort... */
-    pam_conv_had_error = TRUE;
-    return PAM_CONV_ERR;
+      free(reply);
+      pam_conv_had_error = TRUE;
+      return PAM_CONV_ERR;
     }
   }
 

commit 5cb18fca8873da273fb80931b620892586cbffaf
Author: Jeremy Harris <jgh146exb@wizmail.org>
Date:   Fri Nov 8 22:30:04 2019 +0000

    Regard command-line recipients as tainted
    
    (cherry picked from commit f0fe22cbc29ee4f887aa254f2590a9e72401e237)

diff --git a/src/src/exim.c b/src/src/exim.c
index 6a2e7a644..0e839c5d4 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -4822,8 +4822,9 @@ if (verify_address_mode || f.address_test_mode)
     {
     while (recipients_arg < argc)
       {
-      uschar *s = argv[recipients_arg++];
-      while (*s != 0)
+      /* Supplied addresses are tainted since they come from a user */
+      uschar * s = string_copy_taint(argv[recipients_arg++], TRUE);
+      while (*s)
         {
         BOOL finished = FALSE;
         uschar *ss = parse_find_address_end(s, FALSE);
@@ -4831,16 +4832,16 @@ if (verify_address_mode || f.address_test_mode)
         test_address(s, flags, &exit_value);
         s = ss;
         if (!finished)
-          while (*(++s) != 0 && (*s == ',' || isspace(*s)));
+          while (*++s == ',' || isspace(*s)) ;
         }
       }
     }
 
   else for (;;)
     {
-    uschar *s = get_stdinput(NULL, NULL);
-    if (s == NULL) break;
-    test_address(s, flags, &exit_value);
+    uschar * s = get_stdinput(NULL, NULL);
+    if (!s) break;
+    test_address(string_copy_taint(s, TRUE), flags, &exit_value);
     }
 
   route_tidyup();
@@ -5334,13 +5335,13 @@ while (more)
 
     raw_sender = string_copy(sender_address);
 
-    /* Loop for each argument */
+    /* Loop for each argument (supplied by user hence tainted) */
 
     for (int i = 0; i < count; i++)
       {
       int start, end, domain;
-      uschar *errmess;
-      uschar *s = list[i];
+      uschar * errmess;
+      uschar * s = string_copy_taint(list[i], TRUE);
 
       /* Loop for each comma-separated address */
 

commit 0582221c4a875e35b5ccefe9a17eef584819e4f0
Author: Heiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>
Date:   Tue Dec 10 23:14:35 2019 +0100

    TFO: disable for FreeBSD
    
    (cherry-picked from 52503083b9eded01c25e1c73f4510963c3cee799)

diff --git a/src/src/ip.c b/src/src/ip.c
index 19be51a03..70e3e2064 100644
--- a/src/src/ip.c
+++ b/src/src/ip.c
@@ -245,7 +245,7 @@ callout_address = string_sprintf("[%s]:%d", address, port);
 sigalrm_seen = FALSE;
 if (timeout > 0) ALARM(timeout);
 
-#ifdef TCP_FASTOPEN
+#if defined(TCP_FASTOPEN) && (defined(MSG_FASTOPEN) || defined(EXIM_TFO_CONNECTX))
 /* TCP Fast Open, if the system has a cookie from a previous call to
 this peer, can send data in the SYN packet.  The peer can send data
 before it gets our ACK of its SYN,ACK - the latter is useful for
@@ -255,8 +255,8 @@ possibly use the data-on-syn, so support that too. */
 if (fastopen_blob && f.tcp_fastopen_ok)
   {
 # ifdef MSG_FASTOPEN
-  /* This is a Linux implementation.  It might be useable on FreeBSD; I have
-  not checked. */
+  /* This is a Linux implementation.  FreeBSD does not seem to have MSG_FASTOPEN so
+  how to get TFO is unknown. */
 
   if ((rc = sendto(sock, fastopen_blob->data, fastopen_blob->len,
 		    MSG_FASTOPEN | MSG_DONTWAIT, s_ptr, s_len)) >= 0)

commit 6397b292615a5ffb9fdb5bd305736e2ef5f00e0d
Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date:   Wed Dec 4 21:30:01 2019 +0000

    Hurd: errno really uses more than a short-sized value.  Bug 2476
    
    (cherry picked from commit 377da0430697e6bcb8c48744eb5af4272a8f8075)

diff --git a/src/src/structs.h b/src/src/structs.h
index 3b5818df0..c05778161 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -648,11 +648,11 @@ typedef struct address_item {
   unsigned int domain_cache[(MAX_NAMED_LIST * 2)/32];
   unsigned int localpart_cache[(MAX_NAMED_LIST * 2)/32];
   int     mode;                   /* mode for local transporting to a file */
+  int	  basic_errno;		  /* status after failure */
   int     more_errno;             /* additional error information */
                                   /* (may need to hold a timestamp) */
   unsigned int delivery_usec;	  /* subsecond part of delivery time */
 
-  short int basic_errno;          /* status after failure */
   unsigned short child_count;     /* number of child addresses */
   short int return_file;          /* fileno of return data file */
   short int special_action;       /* ( used when when deferred or failed */

commit 8ab104034bd456843cd5a4ab34af6ef339f9ac8d
Author: Jeremy Harris <jgh146exb@wizmail.org>
Date:   Tue Dec 10 20:04:15 2019 +0000

    local_scan: align local_scan.h and docs re. store_get()
    
    (cherry picked from commit 4ec0fcb6737da9bc2603056d56fbf6e41e061967)

diff --git a/src/src/local_scan.h b/src/src/local_scan.h
index e0a97088f..da9a8911a 100644
--- a/src/src/local_scan.h
+++ b/src/src/local_scan.h
@@ -193,6 +193,14 @@ extern void    smtp_vprintf(const char *, BOOL, va_list);
 	string_sprintf_trc(fmt, US __FUNCTION__, __LINE__, __VA_ARGS__)
 extern uschar *string_sprintf_trc(const char *, const uschar *, unsigned, ...) ALMOST_PRINTF(1,4);
 
+#define store_get(size, tainted) \
+	store_get_3(size, tainted, __FUNCTION__, __LINE__)
+extern void   *store_get_3(int, BOOL, const char *, int)	ALLOC ALLOC_SIZE(1) WARN_UNUSED_RESULT;
+#define store_get_perm(size, tainted) \
+	store_get_perm_3(size, tainted, __FUNCTION__, __LINE__)
+extern void   *store_get_perm_3(int, BOOL, const char *, int)	ALLOC ALLOC_SIZE(1) WARN_UNUSED_RESULT;
+
+
 #if defined(LOCAL_SCAN) || defined(DLFUNC_IMPL)
 /* When compiling a local_scan() file we want to rename a published API, so that
 we can use an inlined implementation in the compiles of the main Exim files,
diff --git a/src/src/store.h b/src/src/store.h
index 52f211ef5..39b0f6ecf 100644
--- a/src/src/store.h
+++ b/src/src/store.h
@@ -34,10 +34,7 @@ tracing information for debugging. */
 
 #define store_free(addr) \
 	store_free_3(addr, __FUNCTION__, __LINE__)
-#define store_get(size, tainted) \
-	store_get_3(size, tainted, __FUNCTION__, __LINE__)
-#define store_get_perm(size, tainted) \
-	store_get_perm_3(size, tainted, __FUNCTION__, __LINE__)
+/* store_get & store_get_perm are in local_scan.h */
 #define store_malloc(size) \
 	store_malloc_3(size, __FUNCTION__, __LINE__)
 #define store_mark(void) \
@@ -55,8 +52,7 @@ typedef void ** rmark;
 
 extern BOOL    store_extend_3(void *, BOOL, int, int, const char *, int);
 extern void    store_free_3(void *, const char *, int);
-extern void   *store_get_3(int, BOOL, const char *, int)	ALLOC ALLOC_SIZE(1) WARN_UNUSED_RESULT;
-extern void   *store_get_perm_3(int, BOOL, const char *, int)	ALLOC ALLOC_SIZE(1) WARN_UNUSED_RESULT;
+/* store_get_3 & store_get_perm_3 are in local_scan.h */
 extern void   *store_malloc_3(int, const char *, int)		ALLOC ALLOC_SIZE(1) WARN_UNUSED_RESULT;
 extern rmark   store_mark_3(const char *, int);
 extern void   *store_newblock_3(void *, BOOL, int, int, const char *, int);
