Merge 4.80.1 security fix in.
[exim.git] / src / src / transports / pipe.c
index 35048258e5f0363c6c41bad899c44fb0d30aa91c..32a7bfa7c8bfb751dd1be2c8f24a867aaaefedaf 100644 (file)
@@ -1,5 +1,3 @@
-/* $Cambridge: exim/src/src/transports/pipe.c,v 1.14 2009/11/16 19:50:39 nm4 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
@@ -41,6 +39,8 @@ optionlist pipe_transport_options[] = {
       (void *)offsetof(pipe_transport_options_block, escape_string) },
   { "freeze_exec_fail",  opt_bool,
       (void *)offsetof(pipe_transport_options_block, freeze_exec_fail) },
+  { "freeze_signal",     opt_bool,
+      (void *)offsetof(pipe_transport_options_block, freeze_signal) },
   { "ignore_status",     opt_bool,
       (void *)offsetof(pipe_transport_options_block, ignore_status) },
   { "log_defer_output",  opt_bool | opt_public,
@@ -57,6 +57,8 @@ optionlist pipe_transport_options[] = {
       (void *)offsetof(pipe_transport_options_block, message_suffix) },
   { "path",              opt_stringptr,
       (void *)offsetof(pipe_transport_options_block, path) },
+  { "permit_coredump",   opt_bool,
+      (void *)offsetof(pipe_transport_options_block, permit_coredump) },
   { "pipe_as_creator",   opt_bool | opt_public,
       (void *)offsetof(transport_instance, deliver_as_creator) },
   { "restrict_to_path",  opt_bool,
@@ -109,7 +111,9 @@ pipe_transport_options_block pipe_transport_option_defaults = {
   60*60,          /* timeout */
   0,              /* options */
   FALSE,          /* freeze_exec_fail */
+  FALSE,          /* freeze_signal */
   FALSE,          /* ignore_status */
+  FALSE,          /* permit_coredump */
   FALSE,          /* restrict_to_path */
   FALSE,          /* timeout_defer */
   FALSE,          /* use_shell */
@@ -127,7 +131,7 @@ pipe_transport_options_block pipe_transport_option_defaults = {
 /* Called for each delivery in the privileged state, just before the uid/gid
 are changed and the main entry point is called. In a system that supports the
 login_cap facilities, this function is used to set the class resource limits
-for the user.
+for the user.  It may also re-enable coredumps.
 
 Arguments:
   tblock     points to the transport instance
@@ -170,6 +174,24 @@ if (ob->use_classresources)
   }
 #endif
 
+#ifdef RLIMIT_CORE
+if (ob->permit_coredump)
+  {
+  struct rlimit rl;
+  rl.rlim_cur = RLIM_INFINITY;
+  rl.rlim_max = RLIM_INFINITY;
+  if (setrlimit(RLIMIT_CORE, &rl) < 0)
+    {
+#ifdef SETRLIMIT_NOT_SUPPORTED
+    if (errno != ENOSYS && errno != ENOTSUP)
+#endif
+      log_write(0, LOG_MAIN,
+          "delivery setrlimit(RLIMIT_CORE, RLIM_INFINITY) failed: %s",
+          strerror(errno));
+    }
+  }
+#endif
+
 return OK;
 }
 
@@ -939,11 +961,20 @@ if ((rc = child_close(pid, timeout)) != 0)
   /* Either the process completed, but yielded a non-zero (necessarily
   positive) status, or the process was terminated by a signal (rc will contain
   the negation of the signal number). Treat killing by signal as failure unless
-  status is being ignored. */
+  status is being ignored. By default, the message is bounced back, unless
+  freeze_signal is set, in which case it is frozen instead. */
 
   else if (rc < 0)
     {
-    if (!ob->ignore_status)
+    if (ob->freeze_signal)
+      {
+      addr->transport_return = DEFER;
+      addr->special_action = SPECIAL_FREEZE;
+      addr->message = string_sprintf("Child process of %s transport (running "
+        "command \"%s\") was terminated by signal %d (%s)%s", tblock->name, cmd,
+        -rc, os_strsignal(-rc), tmsg);
+      }
+    else if (!ob->ignore_status)
       {
       addr->transport_return = FAIL;
       addr->message = string_sprintf("Child process of %s transport (running "