Coverage Report

Created: 2022-12-08 06:10

/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
}