Line data Source code
1 : /* exechelp.c - Fork and exec helpers for POSIX
2 : * Copyright (C) 2004, 2007, 2008, 2009,
3 : * 2010 Free Software Foundation, Inc.
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * This file is free software; you can redistribute it and/or modify
8 : * it under the terms of either
9 : *
10 : * - the GNU Lesser General Public License as published by the Free
11 : * Software Foundation; either version 3 of the License, or (at
12 : * your option) any later version.
13 : *
14 : * or
15 : *
16 : * - the GNU General Public License as published by the Free
17 : * Software Foundation; either version 2 of the License, or (at
18 : * your option) any later version.
19 : *
20 : * or both in parallel, as here.
21 : *
22 : * This file is distributed in the hope that it will be useful,
23 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 : * GNU General Public License for more details.
26 : *
27 : * You should have received a copy of the GNU General Public License
28 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
29 : */
30 :
31 : #include <config.h>
32 :
33 : #if defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM)
34 : #error This code is only used on POSIX
35 : #endif
36 :
37 : #include <stdio.h>
38 : #include <stdlib.h>
39 : #ifdef HAVE_STDINT_H
40 : # include <stdint.h>
41 : #endif
42 : #include <string.h>
43 : #include <errno.h>
44 : #include <assert.h>
45 : #ifdef HAVE_SIGNAL_H
46 : # include <signal.h>
47 : #endif
48 : #include <unistd.h>
49 : #include <fcntl.h>
50 :
51 : #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
52 : #undef HAVE_NPTH
53 : #undef USE_NPTH
54 : #endif
55 :
56 : #ifdef HAVE_NPTH
57 : #include <npth.h>
58 : #endif
59 : #include <sys/wait.h>
60 :
61 : #ifdef HAVE_GETRLIMIT
62 : #include <sys/time.h>
63 : #include <sys/resource.h>
64 : #endif /*HAVE_GETRLIMIT*/
65 :
66 : #ifdef HAVE_STAT
67 : # include <sys/stat.h>
68 : #endif
69 :
70 : #include "util.h"
71 : #include "i18n.h"
72 : #include "sysutils.h"
73 : #include "exechelp.h"
74 :
75 :
76 : /* Return the maximum number of currently allowed open file
77 : descriptors. Only useful on POSIX systems but returns a value on
78 : other systems too. */
79 : int
80 18 : get_max_fds (void)
81 : {
82 18 : int max_fds = -1;
83 : #ifdef HAVE_GETRLIMIT
84 : struct rlimit rl;
85 :
86 : # ifdef RLIMIT_NOFILE
87 18 : if (!getrlimit (RLIMIT_NOFILE, &rl))
88 18 : max_fds = rl.rlim_max;
89 : # endif
90 :
91 : # ifdef RLIMIT_OFILE
92 18 : if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
93 0 : max_fds = rl.rlim_max;
94 :
95 : # endif
96 : #endif /*HAVE_GETRLIMIT*/
97 :
98 : #ifdef _SC_OPEN_MAX
99 18 : if (max_fds == -1)
100 : {
101 0 : long int scres = sysconf (_SC_OPEN_MAX);
102 0 : if (scres >= 0)
103 0 : max_fds = scres;
104 : }
105 : #endif
106 :
107 : #ifdef _POSIX_OPEN_MAX
108 : if (max_fds == -1)
109 : max_fds = _POSIX_OPEN_MAX;
110 : #endif
111 :
112 : #ifdef OPEN_MAX
113 : if (max_fds == -1)
114 : max_fds = OPEN_MAX;
115 : #endif
116 :
117 18 : if (max_fds == -1)
118 0 : max_fds = 256; /* Arbitrary limit. */
119 :
120 : /* AIX returns INT32_MAX instead of a proper value. We assume that
121 : this is always an error and use an arbitrary limit. */
122 : #ifdef INT32_MAX
123 18 : if (max_fds == INT32_MAX)
124 0 : max_fds = 256;
125 : #endif
126 :
127 18 : return max_fds;
128 : }
129 :
130 :
131 : /* Close all file descriptors starting with descriptor FIRST. If
132 : EXCEPT is not NULL, it is expected to be a list of file descriptors
133 : which shall not be closed. This list shall be sorted in ascending
134 : order with the end marked by -1. */
135 : void
136 3 : close_all_fds (int first, int *except)
137 : {
138 3 : int max_fd = get_max_fds ();
139 : int fd, i, except_start;
140 :
141 3 : if (except)
142 : {
143 1 : except_start = 0;
144 255998 : for (fd=first; fd < max_fd; fd++)
145 : {
146 256052 : for (i=except_start; except[i] != -1; i++)
147 : {
148 58 : if (except[i] == fd)
149 : {
150 : /* If we found the descriptor in the exception list
151 : we can start the next compare run at the next
152 : index because the exception list is ordered. */
153 3 : except_start = i + 1;
154 3 : break;
155 : }
156 : }
157 255997 : if (except[i] == -1)
158 255994 : close (fd);
159 : }
160 : }
161 : else
162 : {
163 511996 : for (fd=first; fd < max_fd; fd++)
164 511994 : close (fd);
165 : }
166 :
167 3 : gpg_err_set_errno (0);
168 3 : }
169 :
170 :
171 : /* Returns an array with all currently open file descriptors. The end
172 : of the array is marked by -1. The caller needs to release this
173 : array using the *standard free* and not with xfree. This allow the
174 : use of this fucntion right at startup even before libgcrypt has
175 : been initialized. Returns NULL on error and sets ERRNO
176 : accordingly. */
177 : int *
178 13 : get_all_open_fds (void)
179 : {
180 : int *array;
181 : size_t narray;
182 : int fd, max_fd, idx;
183 : #ifndef HAVE_STAT
184 : array = calloc (1, sizeof *array);
185 : if (array)
186 : array[0] = -1;
187 : #else /*HAVE_STAT*/
188 : struct stat statbuf;
189 :
190 13 : max_fd = get_max_fds ();
191 13 : narray = 32; /* If you change this change also t-exechelp.c. */
192 13 : array = calloc (narray, sizeof *array);
193 13 : if (!array)
194 0 : return NULL;
195 :
196 : /* Note: The list we return is ordered. */
197 3328013 : for (idx=0, fd=0; fd < max_fd; fd++)
198 3328000 : if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
199 : {
200 230 : if (idx+1 >= narray)
201 : {
202 : int *tmp;
203 :
204 5 : narray += (narray < 256)? 32:256;
205 5 : tmp = realloc (array, narray * sizeof *array);
206 5 : if (!tmp)
207 : {
208 0 : free (array);
209 0 : return NULL;
210 : }
211 5 : array = tmp;
212 : }
213 230 : array[idx++] = fd;
214 : }
215 13 : array[idx] = -1;
216 : #endif /*HAVE_STAT*/
217 13 : return array;
218 : }
219 :
220 :
221 : /* The exec core used right after the fork. This will never return. */
222 : static void
223 1 : do_exec (const char *pgmname, const char *argv[],
224 : int fd_in, int fd_out, int fd_err,
225 : void (*preexec)(void) )
226 : {
227 : char **arg_list;
228 : int i, j;
229 : int fds[3];
230 :
231 1 : fds[0] = fd_in;
232 1 : fds[1] = fd_out;
233 1 : fds[2] = fd_err;
234 :
235 : /* Create the command line argument array. */
236 1 : i = 0;
237 1 : if (argv)
238 7 : while (argv[i])
239 5 : i++;
240 1 : arg_list = xcalloc (i+2, sizeof *arg_list);
241 1 : arg_list[0] = strrchr (pgmname, '/');
242 1 : if (arg_list[0])
243 1 : arg_list[0]++;
244 : else
245 0 : arg_list[0] = xstrdup (pgmname);
246 1 : if (argv)
247 6 : for (i=0,j=1; argv[i]; i++, j++)
248 5 : arg_list[j] = (char*)argv[i];
249 :
250 : /* Assign /dev/null to unused FDs. */
251 4 : for (i=0; i <= 2; i++)
252 : {
253 3 : if (fds[i] == -1 )
254 : {
255 3 : fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
256 3 : if (fds[i] == -1)
257 0 : log_fatal ("failed to open '%s': %s\n",
258 0 : "/dev/null", strerror (errno));
259 : }
260 : }
261 :
262 : /* Connect the standard files. */
263 4 : for (i=0; i <= 2; i++)
264 : {
265 3 : if (fds[i] != i && dup2 (fds[i], i) == -1)
266 0 : log_fatal ("dup2 std%s failed: %s\n",
267 0 : i==0?"in":i==1?"out":"err", strerror (errno));
268 : }
269 :
270 : /* Close all other files. */
271 1 : close_all_fds (3, NULL);
272 :
273 1 : if (preexec)
274 0 : preexec ();
275 1 : execv (pgmname, arg_list);
276 : /* No way to print anything, as we have closed all streams. */
277 1 : _exit (127);
278 : }
279 :
280 :
281 : static gpg_error_t
282 0 : do_create_pipe (int filedes[2])
283 : {
284 0 : gpg_error_t err = 0;
285 :
286 0 : if (pipe (filedes) == -1)
287 : {
288 0 : err = gpg_error_from_syserror ();
289 0 : filedes[0] = filedes[1] = -1;
290 : }
291 :
292 0 : return err;
293 : }
294 :
295 : /* Portable function to create a pipe. Under Windows the write end is
296 : inheritable. */
297 : gpg_error_t
298 0 : gnupg_create_inbound_pipe (int filedes[2])
299 : {
300 0 : return do_create_pipe (filedes);
301 : }
302 :
303 :
304 : /* Portable function to create a pipe. Under Windows the read end is
305 : inheritable. */
306 : gpg_error_t
307 0 : gnupg_create_outbound_pipe (int filedes[2])
308 : {
309 0 : return do_create_pipe (filedes);
310 : }
311 :
312 :
313 :
314 : static gpg_error_t
315 0 : create_pipe_and_estream (int filedes[2], estream_t *r_fp,
316 : int outbound, int nonblock,
317 : gpg_err_source_t errsource)
318 : {
319 : gpg_error_t err;
320 :
321 0 : if (pipe (filedes) == -1)
322 : {
323 0 : err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
324 0 : log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
325 0 : filedes[0] = filedes[1] = -1;
326 0 : *r_fp = NULL;
327 0 : return err;
328 : }
329 :
330 0 : if (outbound)
331 0 : *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
332 : else
333 0 : *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
334 0 : if (!*r_fp)
335 : {
336 0 : err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
337 0 : log_error (_("error creating a stream for a pipe: %s\n"),
338 : gpg_strerror (err));
339 0 : close (filedes[0]);
340 0 : close (filedes[1]);
341 0 : filedes[0] = filedes[1] = -1;
342 0 : return err;
343 : }
344 0 : return 0;
345 : }
346 :
347 :
348 :
349 : /* Fork and exec the PGMNAME, see exechelp.h for details. */
350 : gpg_error_t
351 0 : gnupg_spawn_process (const char *pgmname, const char *argv[],
352 : gpg_err_source_t errsource,
353 : void (*preexec)(void), unsigned int flags,
354 : estream_t *r_infp,
355 : estream_t *r_outfp,
356 : estream_t *r_errfp,
357 : pid_t *pid)
358 : {
359 : gpg_error_t err;
360 0 : int inpipe[2] = {-1, -1};
361 0 : int outpipe[2] = {-1, -1};
362 0 : int errpipe[2] = {-1, -1};
363 0 : estream_t infp = NULL;
364 0 : estream_t outfp = NULL;
365 0 : estream_t errfp = NULL;
366 0 : int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
367 :
368 0 : if (r_infp)
369 0 : *r_infp = NULL;
370 0 : if (r_outfp)
371 0 : *r_outfp = NULL;
372 0 : if (r_errfp)
373 0 : *r_errfp = NULL;
374 0 : *pid = (pid_t)(-1); /* Always required. */
375 :
376 0 : if (r_infp)
377 : {
378 0 : err = create_pipe_and_estream (inpipe, &infp, 0, nonblock, errsource);
379 0 : if (err)
380 0 : return err;
381 : }
382 :
383 0 : if (r_outfp)
384 : {
385 0 : err = create_pipe_and_estream (outpipe, &outfp, 1, nonblock, errsource);
386 0 : if (err)
387 : {
388 0 : if (infp)
389 0 : es_fclose (infp);
390 0 : else if (inpipe[1] != -1)
391 0 : close (inpipe[1]);
392 0 : if (inpipe[0] != -1)
393 0 : close (inpipe[0]);
394 :
395 0 : return err;
396 : }
397 : }
398 :
399 0 : if (r_errfp)
400 : {
401 0 : err = create_pipe_and_estream (errpipe, &errfp, 1, nonblock, errsource);
402 0 : if (err)
403 : {
404 0 : if (infp)
405 0 : es_fclose (infp);
406 0 : else if (inpipe[1] != -1)
407 0 : close (inpipe[1]);
408 0 : if (inpipe[0] != -1)
409 0 : close (inpipe[0]);
410 :
411 0 : if (outfp)
412 0 : es_fclose (outfp);
413 0 : else if (outpipe[0] != -1)
414 0 : close (outpipe[0]);
415 0 : if (outpipe[1] != -1)
416 0 : close (outpipe[1]);
417 :
418 0 : return err;
419 : }
420 : }
421 :
422 :
423 0 : *pid = fork ();
424 0 : if (*pid == (pid_t)(-1))
425 : {
426 0 : err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
427 0 : log_error (_("error forking process: %s\n"), gpg_strerror (err));
428 :
429 0 : if (infp)
430 0 : es_fclose (infp);
431 0 : else if (inpipe[1] != -1)
432 0 : close (inpipe[1]);
433 0 : if (inpipe[0] != -1)
434 0 : close (inpipe[0]);
435 :
436 0 : if (outfp)
437 0 : es_fclose (outfp);
438 0 : else if (outpipe[0] != -1)
439 0 : close (outpipe[0]);
440 0 : if (outpipe[1] != -1)
441 0 : close (outpipe[1]);
442 :
443 0 : if (errfp)
444 0 : es_fclose (errfp);
445 0 : else if (errpipe[0] != -1)
446 0 : close (errpipe[0]);
447 0 : if (errpipe[1] != -1)
448 0 : close (errpipe[1]);
449 0 : return err;
450 : }
451 :
452 0 : if (!*pid)
453 : {
454 : /* This is the child. */
455 0 : gcry_control (GCRYCTL_TERM_SECMEM);
456 0 : es_fclose (outfp);
457 0 : es_fclose (errfp);
458 0 : do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], preexec);
459 : /*NOTREACHED*/
460 : }
461 :
462 : /* This is the parent. */
463 0 : if (inpipe[0] != -1)
464 0 : close (inpipe[0]);
465 0 : if (outpipe[1] != -1)
466 0 : close (outpipe[1]);
467 0 : if (errpipe[1] != -1)
468 0 : close (errpipe[1]);
469 :
470 0 : if (r_infp)
471 0 : *r_infp = infp;
472 0 : if (r_outfp)
473 0 : *r_outfp = outfp;
474 0 : if (r_errfp)
475 0 : *r_errfp = errfp;
476 :
477 0 : return 0;
478 : }
479 :
480 :
481 :
482 : /* Simplified version of gnupg_spawn_process. This function forks and
483 : then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
484 : and ERRFD to stderr (any of them may be -1 to connect them to
485 : /dev/null). The arguments for the process are expected in the NULL
486 : terminated array ARGV. The program name itself should not be
487 : included there. Calling gnupg_wait_process is required.
488 :
489 : Returns 0 on success or an error code. */
490 : gpg_error_t
491 0 : gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
492 : int infd, int outfd, int errfd, pid_t *pid)
493 : {
494 : gpg_error_t err;
495 :
496 0 : *pid = fork ();
497 0 : if (*pid == (pid_t)(-1))
498 : {
499 0 : err = gpg_error_from_syserror ();
500 0 : log_error (_("error forking process: %s\n"), strerror (errno));
501 0 : return err;
502 : }
503 :
504 0 : if (!*pid)
505 : {
506 0 : gcry_control (GCRYCTL_TERM_SECMEM);
507 : /* Run child. */
508 0 : do_exec (pgmname, argv, infd, outfd, errfd, NULL);
509 : /*NOTREACHED*/
510 : }
511 :
512 0 : return 0;
513 : }
514 :
515 :
516 : /* See exechelp.h for the description. */
517 : gpg_error_t
518 0 : gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
519 : {
520 : gpg_err_code_t ec;
521 : int i, status;
522 :
523 0 : if (r_exitcode)
524 0 : *r_exitcode = -1;
525 :
526 0 : if (pid == (pid_t)(-1))
527 0 : return gpg_error (GPG_ERR_INV_VALUE);
528 :
529 : #ifdef USE_NPTH
530 0 : i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
531 : #else
532 0 : while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
533 0 : && errno == EINTR);
534 : #endif
535 :
536 0 : if (i == (pid_t)(-1))
537 : {
538 0 : ec = gpg_err_code_from_errno (errno);
539 0 : log_error (_("waiting for process %d to terminate failed: %s\n"),
540 0 : (int)pid, strerror (errno));
541 : }
542 0 : else if (!i)
543 : {
544 0 : ec = GPG_ERR_TIMEOUT; /* Still running. */
545 : }
546 0 : else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
547 : {
548 0 : log_error (_("error running '%s': probably not installed\n"), pgmname);
549 0 : ec = GPG_ERR_CONFIGURATION;
550 : }
551 0 : else if (WIFEXITED (status) && WEXITSTATUS (status))
552 0 : {
553 0 : if (!r_exitcode)
554 0 : log_error (_("error running '%s': exit status %d\n"), pgmname,
555 0 : WEXITSTATUS (status));
556 : else
557 0 : *r_exitcode = WEXITSTATUS (status);
558 0 : ec = GPG_ERR_GENERAL;
559 : }
560 0 : else if (!WIFEXITED (status))
561 : {
562 0 : log_error (_("error running '%s': terminated\n"), pgmname);
563 0 : ec = GPG_ERR_GENERAL;
564 : }
565 : else
566 : {
567 0 : if (r_exitcode)
568 0 : *r_exitcode = 0;
569 0 : ec = 0;
570 : }
571 :
572 0 : return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
573 : }
574 :
575 :
576 : void
577 0 : gnupg_release_process (pid_t pid)
578 : {
579 : (void)pid;
580 0 : }
581 :
582 :
583 : /* Spawn a new process and immediately detach from it. The name of
584 : the program to exec is PGMNAME and its arguments are in ARGV (the
585 : programname is automatically passed as first argument).
586 : Environment strings in ENVP are set. An error is returned if
587 : pgmname is not executable; to make this work it is necessary to
588 : provide an absolute file name. All standard file descriptors are
589 : connected to /dev/null. */
590 : gpg_error_t
591 1 : gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
592 : const char *envp[] )
593 : {
594 : pid_t pid;
595 : int i;
596 :
597 1 : if (getuid() != geteuid())
598 0 : return gpg_error (GPG_ERR_BUG);
599 :
600 1 : if (access (pgmname, X_OK))
601 0 : return gpg_error_from_syserror ();
602 :
603 1 : pid = fork ();
604 2 : if (pid == (pid_t)(-1))
605 : {
606 0 : log_error (_("error forking process: %s\n"), strerror (errno));
607 0 : return gpg_error_from_syserror ();
608 : }
609 2 : if (!pid)
610 : {
611 : pid_t pid2;
612 :
613 1 : gcry_control (GCRYCTL_TERM_SECMEM);
614 1 : if (setsid() == -1 || chdir ("/"))
615 0 : _exit (1);
616 :
617 1 : pid2 = fork (); /* Double fork to let init take over the new child. */
618 1 : if (pid2 == (pid_t)(-1))
619 0 : _exit (1);
620 1 : if (pid2)
621 0 : _exit (0); /* Let the parent exit immediately. */
622 :
623 1 : if (envp)
624 0 : for (i=0; envp[i]; i++)
625 0 : putenv (xstrdup (envp[i]));
626 :
627 1 : do_exec (pgmname, argv, -1, -1, -1, NULL);
628 :
629 : /*NOTREACHED*/
630 : }
631 :
632 1 : if (waitpid (pid, NULL, 0) == -1)
633 0 : log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
634 0 : strerror (errno));
635 :
636 1 : return 0;
637 : }
638 :
639 :
640 : /* Kill a process; that is send an appropriate signal to the process.
641 : gnupg_wait_process must be called to actually remove the process
642 : from the system. An invalid PID is ignored. */
643 : void
644 0 : gnupg_kill_process (pid_t pid)
645 : {
646 0 : if (pid != (pid_t)(-1))
647 : {
648 0 : kill (pid, SIGTERM);
649 : }
650 0 : }
|