pass through exec
[exim.git] / src / src / child.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2015 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8
9 #include "exim.h"
10
11 static void (*oldsignal)(int);
12
13
14 /*************************************************
15 *          Ensure an fd has a given value        *
16 *************************************************/
17
18 /* This function is called when we want to ensure that a certain fd has a
19 specific value (one of 0, 1, 2). If it hasn't got it already, close the value
20 we want, duplicate the fd, then close the old one.
21
22 Arguments:
23   oldfd        original fd
24   newfd        the fd we want
25
26 Returns:       nothing
27 */
28
29 static void
30 force_fd(int oldfd, int newfd)
31 {
32 if (oldfd == newfd) return;
33 (void)close(newfd);
34 (void)dup2(oldfd, newfd);
35 (void)close(oldfd);
36 }
37
38
39 #ifndef STAND_ALONE
40 /*************************************************
41 *   Build argv list and optionally re-exec Exim  *
42 *************************************************/
43
44 /* This function is called when Exim wants to re-exec (overlay) itself in the
45 current process. This is different to child_open_exim(), which runs another
46 Exim process in parallel (but it then calls this function). The function's
47 basic job is to build the argv list according to the values of current options
48 settings. There is a basic list that all calls require, and an additional list
49 that some do not require. Further additions can be given as additional
50 arguments. An option specifies whether the exec() is actually to happen, and if
51 so, what is to be done if it fails.
52
53 Arguments:
54   exec_type      CEE_RETURN_ARGV => don't exec; return the argv list
55                  CEE_EXEC_EXIT   => just exit() on exec failure
56                  CEE_EXEC_PANIC  => panic-die on exec failure
57   kill_v         if TRUE, don't pass on the D_v flag
58   pcount         if not NULL, points to extra size of argv required, and if
59                    CEE_RETURN_ARGV is specified, it is updated to give the
60                    number of slots used
61   minimal        TRUE if only minimal argv is required
62   acount         number of additional arguments
63   ...            further values to add to argv
64
65 Returns:         if CEE_RETURN_ARGV is given, returns a pointer to argv;
66                  otherwise, does not return
67 */
68
69 uschar **
70 child_exec_exim(int exec_type, BOOL kill_v, int *pcount, BOOL minimal,
71   int acount, ...)
72 {
73 int first_special = -1;
74 int n = 0;
75 int extra = pcount ? *pcount : 0;
76 uschar **argv;
77
78 argv = store_get((extra + acount + MAX_CLMACROS + 21) * sizeof(char *), FALSE);
79
80 /* In all case, the list starts out with the path, any macros, and a changed
81 config file. */
82
83 argv[n++] = exim_path;
84 if (clmacro_count > 0)
85   {
86   memcpy(argv + n, clmacros, clmacro_count * sizeof(uschar *));
87   n += clmacro_count;
88   }
89 if (f.config_changed)
90   {
91   argv[n++] = US"-C";
92   argv[n++] = config_main_filename;
93   }
94
95 /* These values are added only for non-minimal cases. If debug_selector is
96 precisely D_v, we have to assume this was started by a non-admin user, and
97 we suppress the flag when requested. (This happens when passing on an SMTP
98 connection, and after ETRN.) If there's more debugging going on, an admin user
99 was involved, so we do pass it on. */
100
101 if (!minimal)
102   {
103   if (debug_selector == D_v)
104     {
105     if (!kill_v) argv[n++] = US"-v";
106     }
107   else
108     {
109     if (debug_selector != 0)
110       argv[n++] = string_sprintf("-d=0x%x", debug_selector);
111     }
112   DEBUG(D_any)
113     {
114     argv[n++] = US"-MCd";
115     argv[n++] = US process_purpose;
116     }
117   if (!f.testsuite_delays) argv[n++] = US"-odd";
118   if (f.dont_deliver) argv[n++] = US"-N";
119   if (f.queue_smtp) argv[n++] = US"-odqs";
120   if (f.synchronous_delivery) argv[n++] = US"-odi";
121   if (connection_max_messages >= 0)
122     argv[n++] = string_sprintf("-oB%d", connection_max_messages);
123   if (*queue_name)
124     {
125     argv[n++] = US"-MCG";
126     argv[n++] = queue_name;
127     }
128   }
129
130 /* Now add in any others that are in the call. Remember which they were,
131 for more helpful diagnosis on failure. */
132
133 if (acount > 0)
134   {
135   va_list ap;
136   va_start(ap, acount);
137   first_special = n;
138   while (acount-- > 0)
139     argv[n++] = va_arg(ap, uschar *);
140   va_end(ap);
141   }
142
143 /* Terminate the list, and return it, if that is what is wanted. */
144
145 argv[n] = NULL;
146 if (exec_type == CEE_RETURN_ARGV)
147   {
148   if (pcount != NULL) *pcount = n;
149   return argv;
150   }
151
152 /* Otherwise, do the exec() here, and handle the consequences of an unexpected
153 failure. We know that there will always be at least one extra option in the
154 call when exec() is done here, so it can be used to add to the panic data. */
155
156 DEBUG(D_exec) debug_print_argv(CUSS argv);
157 exim_nullstd();                            /* Make sure std{in,out,err} exist */
158 execv(CS argv[0], (char *const *)argv);
159
160 log_write(0,
161   LOG_MAIN | ((exec_type == CEE_EXEC_EXIT)? LOG_PANIC : LOG_PANIC_DIE),
162   "re-exec of exim (%s) with %s failed: %s", exim_path, argv[first_special],
163   strerror(errno));
164
165 /* Get here if exec_type == CEE_EXEC_EXIT.
166 Note: this must be _exit(), not exit(). */
167
168 _exit(EX_EXECFAILED);
169
170 return NULL;   /* To keep compilers happy */
171 }
172
173
174
175
176 /*************************************************
177 *          Create a child Exim process           *
178 *************************************************/
179
180 /* This function is called when Exim wants to run a parallel instance of itself
181 in order to inject a message via the standard input. The function creates a
182 child process and runs Exim in it. It sets up a pipe to the standard input of
183 the new process, and returns that to the caller via fdptr. The function returns
184 the pid of the new process, or -1 if things go wrong. If debug_fd is
185 non-negative, it is passed as stderr.
186
187 This interface is now a just wrapper for the more complicated function
188 child_open_exim2(), which has additional arguments. The wrapper must continue
189 to exist, even if all calls from within Exim are changed, because it is
190 documented for use from local_scan().
191
192 Argument: fdptr   pointer to int for the stdin fd
193           purpose of the child process, for debug
194 Returns:          pid of the created process or -1 if anything has gone wrong
195 */
196
197 pid_t
198 child_open_exim_function(int * fdptr, const uschar * purpose)
199 {
200 return child_open_exim2_function(fdptr, US"<>", bounce_sender_authentication,
201   purpose);
202 }
203
204
205 /* This is a more complicated function for creating a child Exim process, with
206 more arguments.
207
208 Arguments:
209   fdptr                   pointer to int for the stdin fd
210   sender                  for a sender address (data for -f)
211   sender_authentication   authenticated sender address or NULL
212   purpose                 of the child process, for debug
213
214 Returns:          pid of the created process or -1 if anything has gone wrong
215 */
216
217 pid_t
218 child_open_exim2_function(int * fdptr, uschar * sender,
219   uschar * sender_authentication, const uschar * purpose)
220 {
221 int pfd[2];
222 int save_errno;
223 pid_t pid;
224
225 /* Create the pipe and fork the process. Ensure that SIGCHLD is set to
226 SIG_DFL before forking, so that the child process can be waited for. We
227 sometimes get here with it set otherwise. Save the old state for resetting
228 on the wait. */
229
230 if (pipe(pfd) != 0) return (pid_t)(-1);
231 oldsignal = signal(SIGCHLD, SIG_DFL);
232 pid = exim_fork(purpose);
233
234 /* Child process: make the reading end of the pipe into the standard input and
235 close the writing end. If debugging, pass debug_fd as stderr. Then re-exec
236 Exim with appropriate options. In the test harness, use -odi unless queue_only
237 is set, so that the bounce is fully delivered before returning. Failure is
238 signalled with EX_EXECFAILED (specified by CEE_EXEC_EXIT), but this shouldn't
239 occur. */
240
241 if (pid == 0)
242   {
243   force_fd(pfd[pipe_read], 0);
244   (void)close(pfd[pipe_write]);
245   if (debug_fd > 0) force_fd(debug_fd, 2);
246   if (f.running_in_test_harness && !queue_only)
247     {
248     if (sender_authentication)
249       child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 9,
250         US "-odi", US"-t", US"-oem", US"-oi", US"-f", sender, US"-oMas",
251         sender_authentication, message_id_option);
252     else
253       child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 7,
254         US "-odi", US"-t", US"-oem", US"-oi", US"-f", sender,
255         message_id_option);
256     /* Control does not return here. */
257     }
258   else   /* Not test harness */
259     {
260     if (sender_authentication)
261       child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 8,
262         US"-t", US"-oem", US"-oi", US"-f", sender, US"-oMas",
263         sender_authentication, message_id_option);
264     else
265       child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 6,
266         US"-t", US"-oem", US"-oi", US"-f", sender, message_id_option);
267     /* Control does not return here. */
268     }
269   }
270
271 /* Parent process. Save fork() errno and close the reading end of the stdin
272 pipe. */
273
274 save_errno = errno;
275 (void)close(pfd[pipe_read]);
276
277 /* Fork succeeded */
278
279 if (pid > 0)
280   {
281   *fdptr = pfd[pipe_write];   /* return writing end of stdin pipe */
282   return pid;                 /* and pid of new process */
283   }
284
285 /* Fork failed */
286
287 (void)close(pfd[pipe_write]);
288 errno = save_errno;
289 return (pid_t)(-1);
290 }
291 #endif   /* STAND_ALONE */
292
293
294
295 /*************************************************
296 *         Create a non-Exim child process        *
297 *************************************************/
298
299 /* This function creates a child process and runs the given command in it. It
300 sets up pipes to the standard input and output of the new process, and returns
301 them to the caller. The standard error is cloned to the output. If there are
302 any file descriptors "in the way" in the new process, they are closed. A new
303 umask is supplied for the process, and an optional new uid and gid are also
304 available. These are used by the queryprogram router to set an unprivileged id.
305 SIGUSR1 is always disabled in the new process, as it is not going to be running
306 Exim (the function child_open_exim() is provided for that). This function
307 returns the pid of the new process, or -1 if things go wrong.
308
309 Arguments:
310   argv        the argv for exec in the new process
311   envp        the envp for exec in the new process
312   newumask    umask to set in the new process
313   newuid      point to uid for the new process or NULL for no change
314   newgid      point to gid for the new process or NULL for no change
315   infdptr     pointer to int into which the fd of the stdin of the new process
316                 is placed
317   outfdptr    pointer to int into which the fd of the stdout/stderr of the new
318                 process is placed
319   wd          if not NULL, a path to be handed to chdir() in the new process
320   make_leader if TRUE, make the new process a process group leader
321   purpose     for debug: reason for running the task
322
323 Returns:      the pid of the created process or -1 if anything has gone wrong
324 */
325
326 pid_t
327 child_open_uid(const uschar **argv, const uschar **envp, int newumask,
328   uid_t *newuid, gid_t *newgid, int *infdptr, int *outfdptr, uschar *wd,
329   BOOL make_leader, const uschar * purpose)
330 {
331 int save_errno;
332 int inpfd[2], outpfd[2];
333 pid_t pid;
334
335 /* Create the pipes. */
336
337 if (pipe(inpfd) != 0) return (pid_t)(-1);
338 if (pipe(outpfd) != 0)
339   {
340   (void)close(inpfd[pipe_read]);
341   (void)close(inpfd[pipe_write]);
342   return (pid_t)(-1);
343   }
344
345 /* Fork the process. Ensure that SIGCHLD is set to SIG_DFL before forking, so
346 that the child process can be waited for. We sometimes get here with it set
347 otherwise. Save the old state for resetting on the wait. */
348
349 oldsignal = signal(SIGCHLD, SIG_DFL);
350 pid = exim_fork(purpose);
351
352 /* Handle the child process. First, set the required environment. We must do
353 this before messing with the pipes, in order to be able to write debugging
354 output when things go wrong. */
355
356 if (pid == 0)
357   {
358   signal(SIGUSR1, SIG_IGN);
359   signal(SIGPIPE, SIG_DFL);
360
361   if (newgid && setgid(*newgid) < 0)
362     {
363     DEBUG(D_any) debug_printf("failed to set gid=%ld in subprocess: %s\n",
364       (long int)(*newgid), strerror(errno));
365     goto CHILD_FAILED;
366     }
367
368   if (newuid && setuid(*newuid) < 0)
369     {
370     DEBUG(D_any) debug_printf("failed to set uid=%ld in subprocess: %s\n",
371       (long int)(*newuid), strerror(errno));
372     goto CHILD_FAILED;
373     }
374
375   (void)umask(newumask);
376
377   if (wd && Uchdir(wd) < 0)
378     {
379     DEBUG(D_any) debug_printf("failed to chdir to %s: %s\n", wd,
380       strerror(errno));
381     goto CHILD_FAILED;
382     }
383
384   /* Becomes a process group leader if requested, and then organize the pipes.
385   Any unexpected failure is signalled with EX_EXECFAILED; these are all "should
386   never occur" failures, except for exec failing because the command doesn't
387   exist. */
388
389   if (make_leader && setpgid(0,0) < 0)
390     {
391     DEBUG(D_any) debug_printf("failed to set group leader in subprocess: %s\n",
392       strerror(errno));
393     goto CHILD_FAILED;
394     }
395
396   (void)close(inpfd[pipe_write]);
397   force_fd(inpfd[pipe_read], 0);
398
399   (void)close(outpfd[pipe_read]);
400   force_fd(outpfd[pipe_write], 1);
401
402   (void)close(2);
403   (void)dup2(1, 2);
404
405   /* Now do the exec */
406
407   if (envp) execve(CS argv[0], (char *const *)argv, (char *const *)envp);
408   else execv(CS argv[0], (char *const *)argv);
409
410   /* Failed to execv. Signal this failure using EX_EXECFAILED. We are
411   losing the actual errno we got back, because there is no way to return
412   this information. */
413
414   CHILD_FAILED:
415   _exit(EX_EXECFAILED);      /* Note: must be _exit(), NOT exit() */
416   }
417
418 /* Parent process. Save any fork failure code, and close the reading end of the
419 stdin pipe, and the writing end of the stdout pipe. */
420
421 save_errno = errno;
422 (void)close(inpfd[pipe_read]);
423 (void)close(outpfd[pipe_write]);
424
425 /* Fork succeeded; return the input/output pipes and the pid */
426
427 if (pid > 0)
428   {
429   *infdptr = inpfd[pipe_write];
430   *outfdptr = outpfd[pipe_read];
431   return pid;
432   }
433
434 /* Fork failed; reset fork errno before returning */
435
436 (void)close(inpfd[pipe_write]);
437 (void)close(outpfd[pipe_read]);
438 errno = save_errno;
439 return (pid_t)(-1);
440 }
441
442
443
444
445 /*************************************************
446 *    Create child process without uid change     *
447 *************************************************/
448
449 /* This function is a wrapper for child_open_uid() that doesn't have the uid,
450 gid and working directory changing arguments. The function is provided so as to
451 have a clean interface for use from local_scan(), but also saves writing NULL
452 arguments several calls that would otherwise use child_open_uid().
453
454 Arguments:
455   argv        the argv for exec in the new process
456   envp        the envp for exec in the new process
457   newumask    umask to set in the new process
458   infdptr     pointer to int into which the fd of the stdin of the new process
459                 is placed
460   outfdptr    pointer to int into which the fd of the stdout/stderr of the new
461                 process is placed
462   make_leader if TRUE, make the new process a process group leader
463   purpose     for debug: reason for running the task
464
465 Returns:      the pid of the created process or -1 if anything has gone wrong
466 */
467
468 pid_t
469 child_open_function(uschar **argv, uschar **envp, int newumask, int *infdptr,
470   int *outfdptr, BOOL make_leader, const uschar * purpose)
471 {
472 return child_open_uid(CUSS argv, CUSS envp, newumask, NULL, NULL,
473   infdptr, outfdptr, NULL, make_leader, purpose);
474 }
475
476
477
478
479 /*************************************************
480 *           Close down child process             *
481 *************************************************/
482
483 /* Wait for the given process to finish, with optional timeout.
484
485 Arguments
486   pid:      the pid to wait for
487   timeout:  maximum time to wait; 0 means for as long as it takes
488
489 Returns:    >= 0          process terminated by exiting; value is process
490                             ending status; if an execve() failed, the value
491                             is typically 127 (defined as EX_EXECFAILED)
492             < 0 & > -256  process was terminated by a signal; value is the
493                             negation of the signal number
494             -256          timed out
495             -257          other error in wait(); errno still set
496 */
497
498 int
499 child_close(pid_t pid, int timeout)
500 {
501 int yield;
502
503 if (timeout > 0)
504   {
505   sigalrm_seen = FALSE;
506   ALARM(timeout);
507   }
508
509 for(;;)
510   {
511   int status;
512   pid_t rc = waitpid(pid, &status, 0);
513   if (rc == pid)
514     {
515     int lowbyte = status & 255;
516     yield = lowbyte == 0 ? (status >> 8) & 255 : -lowbyte;
517     break;
518     }
519   if (rc < 0)
520     {
521     /* This "shouldn't happen" test does happen on MacOS: for some reason
522     I do not understand we seems to get an alarm signal despite not having
523     an active alarm set. There seems to be only one, so just go round again. */
524
525     if (errno == EINTR && sigalrm_seen && timeout <= 0) continue;
526
527     yield = (errno == EINTR && sigalrm_seen) ? -256 : -257;
528     break;
529     }
530   }
531
532 if (timeout > 0) ALARM_CLR(0);
533
534 signal(SIGCHLD, oldsignal);   /* restore */
535 return yield;
536 }
537
538 /* End of child.c */