/src/gnupg/common/exechelp-posix.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* exechelp.c - Fork and exec helpers for POSIX |
2 | | * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc. |
3 | | * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH |
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 <https://www.gnu.org/licenses/>. |
29 | | * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+) |
30 | | */ |
31 | | |
32 | | #include <config.h> |
33 | | |
34 | | #if defined(HAVE_W32_SYSTEM) |
35 | | #error This code is only used on POSIX |
36 | | #endif |
37 | | |
38 | | #include <stdio.h> |
39 | | #include <stdlib.h> |
40 | | #include <stdint.h> |
41 | | #include <string.h> |
42 | | #include <errno.h> |
43 | | #include <assert.h> |
44 | | #ifdef HAVE_SIGNAL_H |
45 | | # include <signal.h> |
46 | | #endif |
47 | | #include <unistd.h> |
48 | | #include <fcntl.h> |
49 | | |
50 | | #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */ |
51 | | #undef HAVE_NPTH |
52 | | #undef USE_NPTH |
53 | | #endif |
54 | | |
55 | | #ifdef HAVE_NPTH |
56 | | #include <npth.h> |
57 | | #endif |
58 | | #include <sys/wait.h> |
59 | | |
60 | | #ifdef HAVE_GETRLIMIT |
61 | | #include <sys/time.h> |
62 | | #include <sys/resource.h> |
63 | | #endif /*HAVE_GETRLIMIT*/ |
64 | | |
65 | | #ifdef HAVE_STAT |
66 | | # include <sys/stat.h> |
67 | | #endif |
68 | | |
69 | | #if __linux__ |
70 | | # include <sys/types.h> |
71 | | # include <dirent.h> |
72 | | #endif /*__linux__ */ |
73 | | |
74 | | #include "util.h" |
75 | | #include "i18n.h" |
76 | | #include "sysutils.h" |
77 | | #include "exechelp.h" |
78 | | |
79 | | |
80 | | /* Helper */ |
81 | | static inline gpg_error_t |
82 | | my_error_from_syserror (void) |
83 | 0 | { |
84 | 0 | return gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); |
85 | 0 | } |
86 | | |
87 | | static inline gpg_error_t |
88 | | my_error (int errcode) |
89 | 0 | { |
90 | 0 | return gpg_err_make (default_errsource, errcode); |
91 | 0 | } |
92 | | |
93 | | |
94 | | /* Return the maximum number of currently allowed open file |
95 | | descriptors. Only useful on POSIX systems but returns a value on |
96 | | other systems too. */ |
97 | | int |
98 | | get_max_fds (void) |
99 | 0 | { |
100 | 0 | int max_fds = -1; |
101 | 0 | #ifdef HAVE_GETRLIMIT |
102 | 0 | struct rlimit rl; |
103 | | |
104 | | /* Under Linux we can figure out the highest used file descriptor by |
105 | | * reading /proc/PID/fd. This is in the common cases much fast than |
106 | | * for example doing 4096 close calls where almost all of them will |
107 | | * fail. On a system with a limit of 4096 files and only 8 files |
108 | | * open with the highest number being 10, we speedup close_all_fds |
109 | | * from 125ms to 0.4ms including readdir. |
110 | | * |
111 | | * Another option would be to close the file descriptors as returned |
112 | | * from reading that directory - however then we need to snapshot |
113 | | * that list before starting to close them. */ |
114 | 0 | #ifdef __linux__ |
115 | 0 | { |
116 | 0 | DIR *dir = NULL; |
117 | 0 | struct dirent *dir_entry; |
118 | 0 | const char *s; |
119 | 0 | int x; |
120 | |
|
121 | 0 | dir = opendir ("/proc/self/fd"); |
122 | 0 | if (dir) |
123 | 0 | { |
124 | 0 | while ((dir_entry = readdir (dir))) |
125 | 0 | { |
126 | 0 | s = dir_entry->d_name; |
127 | 0 | if ( *s < '0' || *s > '9') |
128 | 0 | continue; |
129 | 0 | x = atoi (s); |
130 | 0 | if (x > max_fds) |
131 | 0 | max_fds = x; |
132 | 0 | } |
133 | 0 | closedir (dir); |
134 | 0 | } |
135 | 0 | if (max_fds != -1) |
136 | 0 | return max_fds + 1; |
137 | 0 | } |
138 | 0 | #endif /* __linux__ */ |
139 | | |
140 | | |
141 | 0 | # ifdef RLIMIT_NOFILE |
142 | 0 | if (!getrlimit (RLIMIT_NOFILE, &rl)) |
143 | 0 | max_fds = rl.rlim_max; |
144 | 0 | # endif |
145 | |
|
146 | 0 | # ifdef RLIMIT_OFILE |
147 | 0 | if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl)) |
148 | 0 | max_fds = rl.rlim_max; |
149 | |
|
150 | 0 | # endif |
151 | 0 | #endif /*HAVE_GETRLIMIT*/ |
152 | |
|
153 | 0 | #ifdef _SC_OPEN_MAX |
154 | 0 | if (max_fds == -1) |
155 | 0 | { |
156 | 0 | long int scres = sysconf (_SC_OPEN_MAX); |
157 | 0 | if (scres >= 0) |
158 | 0 | max_fds = scres; |
159 | 0 | } |
160 | 0 | #endif |
161 | |
|
162 | 0 | #ifdef _POSIX_OPEN_MAX |
163 | 0 | if (max_fds == -1) |
164 | 0 | max_fds = _POSIX_OPEN_MAX; |
165 | 0 | #endif |
166 | |
|
167 | | #ifdef OPEN_MAX |
168 | | if (max_fds == -1) |
169 | | max_fds = OPEN_MAX; |
170 | | #endif |
171 | |
|
172 | 0 | if (max_fds == -1) |
173 | 0 | max_fds = 256; /* Arbitrary limit. */ |
174 | | |
175 | | /* AIX returns INT32_MAX instead of a proper value. We assume that |
176 | | this is always an error and use an arbitrary limit. */ |
177 | 0 | #ifdef INT32_MAX |
178 | 0 | if (max_fds == INT32_MAX) |
179 | 0 | max_fds = 256; |
180 | 0 | #endif |
181 | |
|
182 | 0 | return max_fds; |
183 | 0 | } |
184 | | |
185 | | |
186 | | /* Close all file descriptors starting with descriptor FIRST. If |
187 | | EXCEPT is not NULL, it is expected to be a list of file descriptors |
188 | | which shall not be closed. This list shall be sorted in ascending |
189 | | order with the end marked by -1. */ |
190 | | void |
191 | | close_all_fds (int first, int *except) |
192 | 0 | { |
193 | 0 | int max_fd = get_max_fds (); |
194 | 0 | int fd, i, except_start; |
195 | |
|
196 | 0 | if (except) |
197 | 0 | { |
198 | 0 | except_start = 0; |
199 | 0 | for (fd=first; fd < max_fd; fd++) |
200 | 0 | { |
201 | 0 | for (i=except_start; except[i] != -1; i++) |
202 | 0 | { |
203 | 0 | if (except[i] == fd) |
204 | 0 | { |
205 | | /* If we found the descriptor in the exception list |
206 | | we can start the next compare run at the next |
207 | | index because the exception list is ordered. */ |
208 | 0 | except_start = i + 1; |
209 | 0 | break; |
210 | 0 | } |
211 | 0 | } |
212 | 0 | if (except[i] == -1) |
213 | 0 | close (fd); |
214 | 0 | } |
215 | 0 | } |
216 | 0 | else |
217 | 0 | { |
218 | 0 | for (fd=first; fd < max_fd; fd++) |
219 | 0 | close (fd); |
220 | 0 | } |
221 | |
|
222 | 0 | gpg_err_set_errno (0); |
223 | 0 | } |
224 | | |
225 | | |
226 | | /* Returns an array with all currently open file descriptors. The end |
227 | | of the array is marked by -1. The caller needs to release this |
228 | | array using the *standard free* and not with xfree. This allow the |
229 | | use of this function right at startup even before libgcrypt has |
230 | | been initialized. Returns NULL on error and sets ERRNO |
231 | | accordingly. */ |
232 | | int * |
233 | | get_all_open_fds (void) |
234 | 0 | { |
235 | 0 | int *array; |
236 | 0 | size_t narray; |
237 | 0 | int fd, max_fd, idx; |
238 | | #ifndef HAVE_STAT |
239 | | array = calloc (1, sizeof *array); |
240 | | if (array) |
241 | | array[0] = -1; |
242 | | #else /*HAVE_STAT*/ |
243 | 0 | struct stat statbuf; |
244 | |
|
245 | 0 | max_fd = get_max_fds (); |
246 | 0 | narray = 32; /* If you change this change also t-exechelp.c. */ |
247 | 0 | array = calloc (narray, sizeof *array); |
248 | 0 | if (!array) |
249 | 0 | return NULL; |
250 | | |
251 | | /* Note: The list we return is ordered. */ |
252 | 0 | for (idx=0, fd=0; fd < max_fd; fd++) |
253 | 0 | if (!(fstat (fd, &statbuf) == -1 && errno == EBADF)) |
254 | 0 | { |
255 | 0 | if (idx+1 >= narray) |
256 | 0 | { |
257 | 0 | int *tmp; |
258 | |
|
259 | 0 | narray += (narray < 256)? 32:256; |
260 | 0 | tmp = realloc (array, narray * sizeof *array); |
261 | 0 | if (!tmp) |
262 | 0 | { |
263 | 0 | free (array); |
264 | 0 | return NULL; |
265 | 0 | } |
266 | 0 | array = tmp; |
267 | 0 | } |
268 | 0 | array[idx++] = fd; |
269 | 0 | } |
270 | 0 | array[idx] = -1; |
271 | 0 | #endif /*HAVE_STAT*/ |
272 | 0 | return array; |
273 | 0 | } |
274 | | |
275 | | |
276 | | /* The exec core used right after the fork. This will never return. */ |
277 | | static void |
278 | | do_exec (const char *pgmname, const char *argv[], |
279 | | int fd_in, int fd_out, int fd_err, |
280 | | int *except, unsigned int flags) |
281 | 0 | { |
282 | 0 | char **arg_list; |
283 | 0 | int i, j; |
284 | 0 | int fds[3]; |
285 | 0 | int nodevnull[3]; |
286 | |
|
287 | 0 | fds[0] = fd_in; |
288 | 0 | fds[1] = fd_out; |
289 | 0 | fds[2] = fd_err; |
290 | |
|
291 | 0 | nodevnull[0] = !!(flags & GNUPG_SPAWN_KEEP_STDIN); |
292 | 0 | nodevnull[1] = !!(flags & GNUPG_SPAWN_KEEP_STDOUT); |
293 | 0 | nodevnull[2] = !!(flags & GNUPG_SPAWN_KEEP_STDERR); |
294 | | |
295 | | /* Create the command line argument array. */ |
296 | 0 | i = 0; |
297 | 0 | if (argv) |
298 | 0 | while (argv[i]) |
299 | 0 | i++; |
300 | 0 | arg_list = xcalloc (i+2, sizeof *arg_list); |
301 | 0 | arg_list[0] = strrchr (pgmname, '/'); |
302 | 0 | if (arg_list[0]) |
303 | 0 | arg_list[0]++; |
304 | 0 | else |
305 | 0 | arg_list[0] = xstrdup (pgmname); |
306 | 0 | if (argv) |
307 | 0 | for (i=0,j=1; argv[i]; i++, j++) |
308 | 0 | arg_list[j] = (char*)argv[i]; |
309 | | |
310 | | /* Assign /dev/null to unused FDs. */ |
311 | 0 | for (i=0; i <= 2; i++) |
312 | 0 | { |
313 | 0 | if (nodevnull[i]) |
314 | 0 | continue; |
315 | 0 | if (fds[i] == -1) |
316 | 0 | { |
317 | 0 | fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY); |
318 | 0 | if (fds[i] == -1) |
319 | 0 | log_fatal ("failed to open '%s': %s\n", |
320 | 0 | "/dev/null", strerror (errno)); |
321 | 0 | } |
322 | 0 | } |
323 | | |
324 | | /* Connect the standard files. */ |
325 | 0 | for (i=0; i <= 2; i++) |
326 | 0 | { |
327 | 0 | if (nodevnull[i]) |
328 | 0 | continue; |
329 | 0 | if (fds[i] != i && dup2 (fds[i], i) == -1) |
330 | 0 | log_fatal ("dup2 std%s failed: %s\n", |
331 | 0 | i==0?"in":i==1?"out":"err", strerror (errno)); |
332 | 0 | } |
333 | | |
334 | | /* Close all other files. */ |
335 | 0 | close_all_fds (3, except); |
336 | |
|
337 | 0 | execv (pgmname, arg_list); |
338 | | /* No way to print anything, as we have closed all streams. */ |
339 | 0 | _exit (127); |
340 | 0 | } |
341 | | |
342 | | |
343 | | static gpg_error_t |
344 | | do_create_pipe (int filedes[2]) |
345 | 0 | { |
346 | 0 | gpg_error_t err = 0; |
347 | |
|
348 | 0 | if (pipe (filedes) == -1) |
349 | 0 | { |
350 | 0 | err = my_error_from_syserror (); |
351 | 0 | filedes[0] = filedes[1] = -1; |
352 | 0 | } |
353 | |
|
354 | 0 | return err; |
355 | 0 | } |
356 | | |
357 | | |
358 | | static gpg_error_t |
359 | | create_pipe_and_estream (int filedes[2], estream_t *r_fp, |
360 | | int outbound, int nonblock) |
361 | 0 | { |
362 | 0 | gpg_error_t err; |
363 | |
|
364 | 0 | if (pipe (filedes) == -1) |
365 | 0 | { |
366 | 0 | err = my_error_from_syserror (); |
367 | 0 | log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); |
368 | 0 | filedes[0] = filedes[1] = -1; |
369 | 0 | *r_fp = NULL; |
370 | 0 | return err; |
371 | 0 | } |
372 | | |
373 | 0 | if (!outbound) |
374 | 0 | *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r"); |
375 | 0 | else |
376 | 0 | *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w"); |
377 | 0 | if (!*r_fp) |
378 | 0 | { |
379 | 0 | err = my_error_from_syserror (); |
380 | 0 | log_error (_("error creating a stream for a pipe: %s\n"), |
381 | 0 | gpg_strerror (err)); |
382 | 0 | close (filedes[0]); |
383 | 0 | close (filedes[1]); |
384 | 0 | filedes[0] = filedes[1] = -1; |
385 | 0 | return err; |
386 | 0 | } |
387 | 0 | return 0; |
388 | 0 | } |
389 | | |
390 | | |
391 | | /* Portable function to create a pipe. Under Windows the write end is |
392 | | inheritable. If R_FP is not NULL, an estream is created for the |
393 | | read end and stored at R_FP. */ |
394 | | gpg_error_t |
395 | | gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock) |
396 | 0 | { |
397 | 0 | if (r_fp) |
398 | 0 | return create_pipe_and_estream (filedes, r_fp, 0, nonblock); |
399 | 0 | else |
400 | 0 | return do_create_pipe (filedes); |
401 | 0 | } |
402 | | |
403 | | |
404 | | /* Portable function to create a pipe. Under Windows the read end is |
405 | | inheritable. If R_FP is not NULL, an estream is created for the |
406 | | write end and stored at R_FP. */ |
407 | | gpg_error_t |
408 | | gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock) |
409 | 0 | { |
410 | 0 | if (r_fp) |
411 | 0 | return create_pipe_and_estream (filedes, r_fp, 1, nonblock); |
412 | 0 | else |
413 | 0 | return do_create_pipe (filedes); |
414 | 0 | } |
415 | | |
416 | | |
417 | | /* Portable function to create a pipe. Under Windows both ends are |
418 | | inheritable. */ |
419 | | gpg_error_t |
420 | | gnupg_create_pipe (int filedes[2]) |
421 | 0 | { |
422 | 0 | return do_create_pipe (filedes); |
423 | 0 | } |
424 | | |
425 | | |
426 | | /* Close the end of a pipe. */ |
427 | | void |
428 | | gnupg_close_pipe (int fd) |
429 | 0 | { |
430 | 0 | if (fd != -1) |
431 | 0 | close (fd); |
432 | 0 | } |
433 | | |
434 | | |
435 | | /* Fork and exec the PGMNAME, see exechelp.h for details. */ |
436 | | gpg_error_t |
437 | | gnupg_spawn_process (const char *pgmname, const char *argv[], |
438 | | int *except, unsigned int flags, |
439 | | estream_t *r_infp, |
440 | | estream_t *r_outfp, |
441 | | estream_t *r_errfp, |
442 | | pid_t *pid) |
443 | 0 | { |
444 | 0 | gpg_error_t err; |
445 | 0 | int inpipe[2] = {-1, -1}; |
446 | 0 | int outpipe[2] = {-1, -1}; |
447 | 0 | int errpipe[2] = {-1, -1}; |
448 | 0 | estream_t infp = NULL; |
449 | 0 | estream_t outfp = NULL; |
450 | 0 | estream_t errfp = NULL; |
451 | 0 | int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK); |
452 | |
|
453 | 0 | if (r_infp) |
454 | 0 | *r_infp = NULL; |
455 | 0 | if (r_outfp) |
456 | 0 | *r_outfp = NULL; |
457 | 0 | if (r_errfp) |
458 | 0 | *r_errfp = NULL; |
459 | 0 | *pid = (pid_t)(-1); /* Always required. */ |
460 | |
|
461 | 0 | if (r_infp) |
462 | 0 | { |
463 | 0 | err = create_pipe_and_estream (inpipe, &infp, 1, nonblock); |
464 | 0 | if (err) |
465 | 0 | return err; |
466 | 0 | } |
467 | | |
468 | 0 | if (r_outfp) |
469 | 0 | { |
470 | 0 | err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock); |
471 | 0 | if (err) |
472 | 0 | { |
473 | 0 | if (infp) |
474 | 0 | es_fclose (infp); |
475 | 0 | else if (inpipe[1] != -1) |
476 | 0 | close (inpipe[1]); |
477 | 0 | if (inpipe[0] != -1) |
478 | 0 | close (inpipe[0]); |
479 | |
|
480 | 0 | return err; |
481 | 0 | } |
482 | 0 | } |
483 | | |
484 | 0 | if (r_errfp) |
485 | 0 | { |
486 | 0 | err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock); |
487 | 0 | if (err) |
488 | 0 | { |
489 | 0 | if (infp) |
490 | 0 | es_fclose (infp); |
491 | 0 | else if (inpipe[1] != -1) |
492 | 0 | close (inpipe[1]); |
493 | 0 | if (inpipe[0] != -1) |
494 | 0 | close (inpipe[0]); |
495 | |
|
496 | 0 | if (outfp) |
497 | 0 | es_fclose (outfp); |
498 | 0 | else if (outpipe[0] != -1) |
499 | 0 | close (outpipe[0]); |
500 | 0 | if (outpipe[1] != -1) |
501 | 0 | close (outpipe[1]); |
502 | |
|
503 | 0 | return err; |
504 | 0 | } |
505 | 0 | } |
506 | | |
507 | | |
508 | 0 | *pid = fork (); |
509 | 0 | if (*pid == (pid_t)(-1)) |
510 | 0 | { |
511 | 0 | err = my_error_from_syserror (); |
512 | 0 | log_error (_("error forking process: %s\n"), gpg_strerror (err)); |
513 | |
|
514 | 0 | if (infp) |
515 | 0 | es_fclose (infp); |
516 | 0 | else if (inpipe[1] != -1) |
517 | 0 | close (inpipe[1]); |
518 | 0 | if (inpipe[0] != -1) |
519 | 0 | close (inpipe[0]); |
520 | |
|
521 | 0 | if (outfp) |
522 | 0 | es_fclose (outfp); |
523 | 0 | else if (outpipe[0] != -1) |
524 | 0 | close (outpipe[0]); |
525 | 0 | if (outpipe[1] != -1) |
526 | 0 | close (outpipe[1]); |
527 | |
|
528 | 0 | if (errfp) |
529 | 0 | es_fclose (errfp); |
530 | 0 | else if (errpipe[0] != -1) |
531 | 0 | close (errpipe[0]); |
532 | 0 | if (errpipe[1] != -1) |
533 | 0 | close (errpipe[1]); |
534 | 0 | return err; |
535 | 0 | } |
536 | | |
537 | 0 | if (!*pid) |
538 | 0 | { |
539 | | /* This is the child. */ |
540 | 0 | gcry_control (GCRYCTL_TERM_SECMEM); |
541 | 0 | es_fclose (infp); |
542 | 0 | es_fclose (outfp); |
543 | 0 | es_fclose (errfp); |
544 | 0 | do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], |
545 | 0 | except, flags); |
546 | | /*NOTREACHED*/ |
547 | 0 | } |
548 | | |
549 | | /* This is the parent. */ |
550 | 0 | if (inpipe[0] != -1) |
551 | 0 | close (inpipe[0]); |
552 | 0 | if (outpipe[1] != -1) |
553 | 0 | close (outpipe[1]); |
554 | 0 | if (errpipe[1] != -1) |
555 | 0 | close (errpipe[1]); |
556 | |
|
557 | 0 | if (r_infp) |
558 | 0 | *r_infp = infp; |
559 | 0 | if (r_outfp) |
560 | 0 | *r_outfp = outfp; |
561 | 0 | if (r_errfp) |
562 | 0 | *r_errfp = errfp; |
563 | |
|
564 | 0 | return 0; |
565 | 0 | } |
566 | | |
567 | | |
568 | | |
569 | | /* Simplified version of gnupg_spawn_process. This function forks and |
570 | | then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout |
571 | | and ERRFD to stderr (any of them may be -1 to connect them to |
572 | | /dev/null). The arguments for the process are expected in the NULL |
573 | | terminated array ARGV. The program name itself should not be |
574 | | included there. Calling gnupg_wait_process is required. |
575 | | |
576 | | Returns 0 on success or an error code. */ |
577 | | gpg_error_t |
578 | | gnupg_spawn_process_fd (const char *pgmname, const char *argv[], |
579 | | int infd, int outfd, int errfd, pid_t *pid) |
580 | 0 | { |
581 | 0 | gpg_error_t err; |
582 | |
|
583 | 0 | *pid = fork (); |
584 | 0 | if (*pid == (pid_t)(-1)) |
585 | 0 | { |
586 | 0 | err = my_error_from_syserror (); |
587 | 0 | log_error (_("error forking process: %s\n"), strerror (errno)); |
588 | 0 | return err; |
589 | 0 | } |
590 | | |
591 | 0 | if (!*pid) |
592 | 0 | { |
593 | 0 | gcry_control (GCRYCTL_TERM_SECMEM); |
594 | | /* Run child. */ |
595 | 0 | do_exec (pgmname, argv, infd, outfd, errfd, NULL, 0); |
596 | | /*NOTREACHED*/ |
597 | 0 | } |
598 | |
|
599 | 0 | return 0; |
600 | 0 | } |
601 | | |
602 | | |
603 | | |
604 | | |
605 | | /* Waiting for child processes. |
606 | | |
607 | | waitpid(2) may return information about terminated children that we |
608 | | did not yet request, and there is no portable way to wait for a |
609 | | specific set of children. |
610 | | |
611 | | As a workaround, we store the results of children for later use. |
612 | | |
613 | | XXX: This assumes that PIDs are not reused too quickly. */ |
614 | | |
615 | | struct terminated_child |
616 | | { |
617 | | pid_t pid; |
618 | | int exitcode; |
619 | | struct terminated_child *next; |
620 | | }; |
621 | | |
622 | | struct terminated_child *terminated_children; |
623 | | |
624 | | |
625 | | static gpg_error_t |
626 | | store_result (pid_t pid, int exitcode) |
627 | 0 | { |
628 | 0 | struct terminated_child *c; |
629 | |
|
630 | 0 | c = xtrymalloc (sizeof *c); |
631 | 0 | if (c == NULL) |
632 | 0 | return gpg_err_code_from_syserror (); |
633 | | |
634 | 0 | c->pid = pid; |
635 | 0 | c->exitcode = exitcode; |
636 | 0 | c->next = terminated_children; |
637 | 0 | terminated_children = c; |
638 | |
|
639 | 0 | return 0; |
640 | 0 | } |
641 | | |
642 | | |
643 | | static int |
644 | | get_result (pid_t pid, int *r_exitcode) |
645 | 0 | { |
646 | 0 | struct terminated_child *c, **prevp; |
647 | |
|
648 | 0 | for (prevp = &terminated_children, c = terminated_children; |
649 | 0 | c; |
650 | 0 | prevp = &c->next, c = c->next) |
651 | 0 | if (c->pid == pid) |
652 | 0 | { |
653 | 0 | *prevp = c->next; |
654 | 0 | *r_exitcode = c->exitcode; |
655 | 0 | xfree (c); |
656 | 0 | return 1; |
657 | 0 | } |
658 | | |
659 | 0 | return 0; |
660 | 0 | } |
661 | | |
662 | | |
663 | | /* See exechelp.h for a description. */ |
664 | | gpg_error_t |
665 | | gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) |
666 | 0 | { |
667 | 0 | gpg_err_code_t ec; |
668 | 0 | int i, status; |
669 | |
|
670 | 0 | if (r_exitcode) |
671 | 0 | *r_exitcode = -1; |
672 | |
|
673 | 0 | if (pid == (pid_t)(-1)) |
674 | 0 | return gpg_error (GPG_ERR_INV_VALUE); |
675 | | |
676 | | #ifdef USE_NPTH |
677 | | i = npth_waitpid (pid, &status, hang? 0:WNOHANG); |
678 | | #else |
679 | 0 | while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1) |
680 | 0 | && errno == EINTR); |
681 | 0 | #endif |
682 | |
|
683 | 0 | if (i == (pid_t)(-1)) |
684 | 0 | { |
685 | 0 | ec = gpg_err_code_from_errno (errno); |
686 | 0 | log_error (_("waiting for process %d to terminate failed: %s\n"), |
687 | 0 | (int)pid, strerror (errno)); |
688 | 0 | } |
689 | 0 | else if (!i) |
690 | 0 | { |
691 | 0 | ec = GPG_ERR_TIMEOUT; /* Still running. */ |
692 | 0 | } |
693 | 0 | else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) |
694 | 0 | { |
695 | 0 | log_error (_("error running '%s': probably not installed\n"), pgmname); |
696 | 0 | ec = GPG_ERR_CONFIGURATION; |
697 | 0 | } |
698 | 0 | else if (WIFEXITED (status) && WEXITSTATUS (status)) |
699 | 0 | { |
700 | 0 | if (!r_exitcode) |
701 | 0 | log_error (_("error running '%s': exit status %d\n"), pgmname, |
702 | 0 | WEXITSTATUS (status)); |
703 | 0 | else |
704 | 0 | *r_exitcode = WEXITSTATUS (status); |
705 | 0 | ec = GPG_ERR_GENERAL; |
706 | 0 | } |
707 | 0 | else if (!WIFEXITED (status)) |
708 | 0 | { |
709 | 0 | log_error (_("error running '%s': terminated\n"), pgmname); |
710 | 0 | ec = GPG_ERR_GENERAL; |
711 | 0 | } |
712 | 0 | else |
713 | 0 | { |
714 | 0 | if (r_exitcode) |
715 | 0 | *r_exitcode = 0; |
716 | 0 | ec = 0; |
717 | 0 | } |
718 | |
|
719 | 0 | return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); |
720 | 0 | } |
721 | | |
722 | | /* See exechelp.h for a description. */ |
723 | | gpg_error_t |
724 | | gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, |
725 | | int hang, int *r_exitcodes) |
726 | 0 | { |
727 | 0 | gpg_err_code_t ec = 0; |
728 | 0 | size_t i, left; |
729 | 0 | int *dummy = NULL; |
730 | |
|
731 | 0 | if (r_exitcodes == NULL) |
732 | 0 | { |
733 | 0 | dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count); |
734 | 0 | if (dummy == NULL) |
735 | 0 | return gpg_err_code_from_syserror (); |
736 | 0 | } |
737 | | |
738 | 0 | for (i = 0, left = count; i < count; i++) |
739 | 0 | { |
740 | 0 | int status = -1; |
741 | | |
742 | | /* Skip invalid PID. */ |
743 | 0 | if (pids[i] == (pid_t)(-1)) |
744 | 0 | { |
745 | 0 | r_exitcodes[i] = -1; |
746 | 0 | left -= 1; |
747 | 0 | continue; |
748 | 0 | } |
749 | | |
750 | | /* See if there was a previously stored result for this pid. */ |
751 | 0 | if (get_result (pids[i], &status)) |
752 | 0 | left -= 1; |
753 | |
|
754 | 0 | r_exitcodes[i] = status; |
755 | 0 | } |
756 | |
|
757 | 0 | while (left > 0) |
758 | 0 | { |
759 | 0 | pid_t pid; |
760 | 0 | int status; |
761 | |
|
762 | | #ifdef USE_NPTH |
763 | | pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG); |
764 | | #else |
765 | 0 | while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1) |
766 | 0 | && errno == EINTR); |
767 | 0 | #endif |
768 | |
|
769 | 0 | if (pid == (pid_t)(-1)) |
770 | 0 | { |
771 | 0 | ec = gpg_err_code_from_errno (errno); |
772 | 0 | log_error (_("waiting for processes to terminate failed: %s\n"), |
773 | 0 | strerror (errno)); |
774 | 0 | break; |
775 | 0 | } |
776 | 0 | else if (!pid) |
777 | 0 | { |
778 | 0 | ec = GPG_ERR_TIMEOUT; /* Still running. */ |
779 | 0 | break; |
780 | 0 | } |
781 | 0 | else |
782 | 0 | { |
783 | 0 | for (i = 0; i < count; i++) |
784 | 0 | if (pid == pids[i]) |
785 | 0 | break; |
786 | |
|
787 | 0 | if (i == count) |
788 | 0 | { |
789 | | /* No match, store this result. */ |
790 | 0 | ec = store_result (pid, status); |
791 | 0 | if (ec) |
792 | 0 | break; |
793 | 0 | continue; |
794 | 0 | } |
795 | | |
796 | | /* Process PIDS[i] died. */ |
797 | 0 | if (r_exitcodes[i] != (pid_t) -1) |
798 | 0 | { |
799 | 0 | log_error ("PID %d was reused", pid); |
800 | 0 | ec = GPG_ERR_GENERAL; |
801 | 0 | break; |
802 | 0 | } |
803 | | |
804 | 0 | left -= 1; |
805 | 0 | r_exitcodes[i] = status; |
806 | 0 | } |
807 | 0 | } |
808 | |
|
809 | 0 | for (i = 0; i < count; i++) |
810 | 0 | { |
811 | 0 | if (r_exitcodes[i] == -1) |
812 | 0 | continue; |
813 | | |
814 | 0 | if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127) |
815 | 0 | { |
816 | 0 | log_error (_("error running '%s': probably not installed\n"), |
817 | 0 | pgmnames[i]); |
818 | 0 | ec = GPG_ERR_CONFIGURATION; |
819 | 0 | } |
820 | 0 | else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i])) |
821 | 0 | { |
822 | 0 | if (dummy) |
823 | 0 | log_error (_("error running '%s': exit status %d\n"), |
824 | 0 | pgmnames[i], WEXITSTATUS (r_exitcodes[i])); |
825 | 0 | else |
826 | 0 | r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]); |
827 | 0 | ec = GPG_ERR_GENERAL; |
828 | 0 | } |
829 | 0 | else if (!WIFEXITED (r_exitcodes[i])) |
830 | 0 | { |
831 | 0 | log_error (_("error running '%s': terminated\n"), pgmnames[i]); |
832 | 0 | ec = GPG_ERR_GENERAL; |
833 | 0 | } |
834 | 0 | } |
835 | |
|
836 | 0 | xfree (dummy); |
837 | 0 | return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); |
838 | 0 | } |
839 | | |
840 | | |
841 | | |
842 | | void |
843 | | gnupg_release_process (pid_t pid) |
844 | 0 | { |
845 | 0 | (void)pid; |
846 | 0 | } |
847 | | |
848 | | |
849 | | /* Spawn a new process and immediately detach from it. The name of |
850 | | the program to exec is PGMNAME and its arguments are in ARGV (the |
851 | | programname is automatically passed as first argument). |
852 | | Environment strings in ENVP are set. An error is returned if |
853 | | pgmname is not executable; to make this work it is necessary to |
854 | | provide an absolute file name. All standard file descriptors are |
855 | | connected to /dev/null. */ |
856 | | gpg_error_t |
857 | | gnupg_spawn_process_detached (const char *pgmname, const char *argv[], |
858 | | const char *envp[] ) |
859 | 0 | { |
860 | 0 | gpg_err_code_t ec; |
861 | 0 | pid_t pid; |
862 | 0 | int i; |
863 | |
|
864 | 0 | if (getuid() != geteuid()) |
865 | 0 | return my_error (GPG_ERR_BUG); |
866 | | |
867 | 0 | if ((ec = gnupg_access (pgmname, X_OK))) |
868 | 0 | return gpg_err_make (default_errsource, ec); |
869 | | |
870 | 0 | pid = fork (); |
871 | 0 | if (pid == (pid_t)(-1)) |
872 | 0 | { |
873 | 0 | log_error (_("error forking process: %s\n"), strerror (errno)); |
874 | 0 | return my_error_from_syserror (); |
875 | 0 | } |
876 | 0 | if (!pid) |
877 | 0 | { |
878 | 0 | pid_t pid2; |
879 | |
|
880 | 0 | gcry_control (GCRYCTL_TERM_SECMEM); |
881 | 0 | if (setsid() == -1 || chdir ("/")) |
882 | 0 | _exit (1); |
883 | | |
884 | 0 | pid2 = fork (); /* Double fork to let init take over the new child. */ |
885 | 0 | if (pid2 == (pid_t)(-1)) |
886 | 0 | _exit (1); |
887 | 0 | if (pid2) |
888 | 0 | _exit (0); /* Let the parent exit immediately. */ |
889 | | |
890 | 0 | if (envp) |
891 | 0 | for (i=0; envp[i]; i++) |
892 | 0 | putenv (xstrdup (envp[i])); |
893 | |
|
894 | 0 | do_exec (pgmname, argv, -1, -1, -1, NULL, 0); |
895 | | |
896 | | /*NOTREACHED*/ |
897 | 0 | } |
898 | | |
899 | 0 | if (waitpid (pid, NULL, 0) == -1) |
900 | 0 | log_error ("waitpid failed in gnupg_spawn_process_detached: %s", |
901 | 0 | strerror (errno)); |
902 | |
|
903 | 0 | return 0; |
904 | 0 | } |
905 | | |
906 | | |
907 | | /* Kill a process; that is send an appropriate signal to the process. |
908 | | gnupg_wait_process must be called to actually remove the process |
909 | | from the system. An invalid PID is ignored. */ |
910 | | void |
911 | | gnupg_kill_process (pid_t pid) |
912 | 0 | { |
913 | 0 | if (pid != (pid_t)(-1)) |
914 | 0 | { |
915 | 0 | kill (pid, SIGTERM); |
916 | 0 | } |
917 | 0 | } |