smtp_accept_map_per_host: call search_tidyup in fail path. Bug 2597
authorJeremy Harris <jgh146exb@wizmail.org>
Fri, 12 Jun 2020 19:17:56 +0000 (20:17 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Fri, 12 Jun 2020 19:17:56 +0000 (20:17 +0100)
doc/doc-txt/ChangeLog
src/src/daemon.c
src/src/lookups/ldap.c

index 7284f9cfe3d8a5608f4816b50d5a305278474604..86686521ed6b017f512701216780dc5fc5ca860d 100644 (file)
@@ -35,6 +35,11 @@ JH/06 Bug 2594: Change the name used for certificate name checks in the smtp
       the head of the CNAME chain leading there (if there is one).  This seems
       to align better with RFC 6125.
 
       the head of the CNAME chain leading there (if there is one).  This seems
       to align better with RFC 6125.
 
+JH/07 Bug 2597: Fix a resource leak.  Using a lookup in obtaining a value for
+      smtp_accept_max_per_host allocated resources which were not released
+      when the limit was exceeded.  This eventually crashed the daemon.  Fix
+      by adding a relase action in that path.
+
 
 Exim version 4.94
 -----------------
 
 Exim version 4.94
 -----------------
index 1816537ecfc055d17cd639961ee41b3fa630cd92..8c9abc7dcc34227f65e2f046ddcc4a10b7505cee 100644 (file)
@@ -278,10 +278,10 @@ to provide host-specific limits according to $sender_host address, but because
 this is in the daemon mainline, only fast expansions (such as inline address
 checks) should be used. The documentation is full of warnings. */
 
 this is in the daemon mainline, only fast expansions (such as inline address
 checks) should be used. The documentation is full of warnings. */
 
-if (smtp_accept_max_per_host != NULL)
+if (smtp_accept_max_per_host)
   {
   uschar *expanded = expand_string(smtp_accept_max_per_host);
   {
   uschar *expanded = expand_string(smtp_accept_max_per_host);
-  if (expanded == NULL)
+  if (!expanded)
     {
     if (!f.expand_string_forcedfail)
       log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
     {
     if (!f.expand_string_forcedfail)
       log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
@@ -293,7 +293,7 @@ if (smtp_accept_max_per_host != NULL)
     uschar *s = expanded;
     while (isdigit(*s))
       max_for_this_host = max_for_this_host * 10 + *s++ - '0';
     uschar *s = expanded;
     while (isdigit(*s))
       max_for_this_host = max_for_this_host * 10 + *s++ - '0';
-    if (*s != 0)
+    if (*s)
       log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
         "for %s contains non-digit: %s", whofrom->s, expanded);
     }
       log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
         "for %s contains non-digit: %s", whofrom->s, expanded);
     }
@@ -303,8 +303,7 @@ if (smtp_accept_max_per_host != NULL)
 per host_address checks. Note that at this stage smtp_accept_count contains the
 count of *other* connections, not including this one. */
 
 per host_address checks. Note that at this stage smtp_accept_count contains the
 count of *other* connections, not including this one. */
 
-if ((max_for_this_host > 0) &&
-    (smtp_accept_count >= max_for_this_host))
+if (max_for_this_host > 0 && smtp_accept_count >= max_for_this_host)
   {
   int host_accept_count = 0;
   int other_host_count = 0;    /* keep a count of non matches to optimise */
   {
   int host_accept_count = 0;
   int other_host_count = 0;    /* keep a count of non matches to optimise */
@@ -321,8 +320,8 @@ if ((max_for_this_host > 0) &&
       early, either by hitting the target, or finding there are not enough
       connections left to make the target. */
 
       early, either by hitting the target, or finding there are not enough
       connections left to make the target. */
 
-      if ((host_accept_count >= max_for_this_host) ||
-         ((smtp_accept_count - other_host_count) < max_for_this_host))
+      if (  host_accept_count >= max_for_this_host
+         || smtp_accept_count - other_host_count < max_for_this_host)
        break;
       }
 
        break;
       }
 
@@ -336,6 +335,7 @@ if ((max_for_this_host > 0) &&
     log_write(L_connection_reject,
               LOG_MAIN, "Connection from %s refused: too many connections "
       "from that IP address", whofrom->s);
     log_write(L_connection_reject,
               LOG_MAIN, "Connection from %s refused: too many connections "
       "from that IP address", whofrom->s);
+    search_tidyup();
     goto ERROR_RETURN;
     }
   }
     goto ERROR_RETURN;
     }
   }
index ef550a08dcb3cc376954b05274ed66d289a91391..3fced1cbd346eab1ab935a0f8bf3216a268b0d8c 100644 (file)
@@ -1348,16 +1348,13 @@ Make sure that eldap_dn does not refer to reclaimed or worse, freed store */
 static void
 eldap_tidy(void)
 {
 static void
 eldap_tidy(void)
 {
-LDAP_CONNECTION *lcp = NULL;
 eldap_dn = NULL;
 
 eldap_dn = NULL;
 
-while ((lcp = ldap_connections) != NULL)
+for (LDAP_CONNECTION *lcp; lcp = ldap_connections; ldap_connections = lcp->next)
   {
   {
-  DEBUG(D_lookup) debug_printf_indent("unbind LDAP connection to %s:%d\n", lcp->host,
-    lcp->port);
-  if(lcp->bound == TRUE)
-    ldap_unbind(lcp->ld);
-  ldap_connections = lcp->next;
+  DEBUG(D_lookup) debug_printf_indent("unbind LDAP connection to %s:%d\n",
+    lcp->host, lcp->port);
+  if(lcp->bound) ldap_unbind(lcp->ld);
   }
 }
 
   }
 }