1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Make sure not to leak file descriptors if running gpg-agent with a

command.  Restore the signal mask to solve a problem in Mono.
This commit is contained in:
Werner Koch 2009-03-19 07:09:31 +00:00
parent a3b63ac1dc
commit 588a7c34bb
11 changed files with 252 additions and 28 deletions

View file

@ -1,3 +1,8 @@
2009-03-19 Werner Koch <wk@g10code.com>
* gpg-agent.c (main): Save signal mask and open fds. Restore mask
and close all fds prior to the exec. Fixes bug#1013.
2009-03-17 Werner Koch <wk@g10code.com>
* command.c (cmd_get_passphrase): Break repeat loop on error.

View file

@ -47,6 +47,7 @@
#include "sysutils.h"
#include "setenv.h"
#include "gc-opt-flags.h"
#include "exechelp.h"
enum cmd_and_opt_values
@ -197,6 +198,17 @@ static ARGPARSE_OPTS opts[] = {
#define TIMERTICK_INTERVAL (2) /* Seconds. */
#endif
/* The list of open file descriptors at startup. Note that this list
has been allocated using the standard malloc. */
static int *startup_fd_list;
/* The signal mask at startup and a flag telling whether it is valid. */
#ifdef HAVE_SIGPROCMASK
static sigset_t startup_signal_mask;
static int startup_signal_mask_valid;
#endif
/* Flag to indicate that a shutdown was requested. */
static int shutdown_pending;
@ -530,6 +542,16 @@ main (int argc, char **argv )
const char *env_file_name = NULL;
/* Before we do anything else we save the list of currently open
file descriptors and the signal mask. This info is required to
do the exec call properly. */
startup_fd_list = get_all_open_fds ();
#ifdef HAVE_SIGPROCMASK
if (!sigprocmask (SIG_UNBLOCK, NULL, &startup_signal_mask))
startup_signal_mask_valid = 1;
#endif /*HAVE_SIGPROCMASK*/
/* Set program name etc. */
set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
/* Please note that we may running SUID(ROOT), so be very CAREFUL
@ -961,6 +983,27 @@ main (int argc, char **argv )
close (fd);
/* Note that we used a standard fork so that Pth runs in
both the parent and the child. The pth_fork would
terminate Pth in the child but that is not the way we
want it. Thus we use a plain fork and terminate Pth here
in the parent. The pth_kill may or may not work reliable
but it should not harm to call it. Because Pth fiddles
with the signal mask the signal mask might not be correct
right now and thus we restore it. That is not strictly
necessary but some programs falsely assume a cleared
signal mask. */
#ifdef HAVE_SIGPROCMASK
if (startup_signal_mask_valid)
{
if (sigprocmask (SIG_SETMASK, &startup_signal_mask, NULL))
log_error ("error restoring signal mask: %s\n",
strerror (errno));
}
else
log_info ("no saved signal mask\n");
#endif /*HAVE_SIGPROCMASK*/
/* Create the info string: <name>:<pid>:<protocol_version> */
if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
socket_name, (ulong)pid ) < 0)
@ -1039,6 +1082,14 @@ main (int argc, char **argv )
kill (pid, SIGTERM );
exit (1);
}
/* Close all the file descriptors except the standard
ones and those open at startup. We explicitly don't
close 0,1,2 in case something went wrong collecting
them at startup. */
close_all_fds (3, startup_fd_list);
/* Run the command. */
execvp (argv[0], argv);
log_error ("failed to run the command: %s\n", strerror (errno));
kill (pid, SIGTERM);