1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-03-28 22:49:59 +01:00

agent: Use a thread to monitor socket takeover.

* agent/gpg-agent.c (check_own_socket_running): Remove.
(socket_takeover_detected): New.
(check_own_socket): Remove.
(handle_tick): Don't call check_own_socket any more.
(handle_connections): Start off the check_own_socket_thread.
Check socket_takeover_detected to handle the event.
(do_check_own_socket): New, factoring out the task.
(check_own_socket_thread): Loop with the interval.

--

GnuPG-bug-id: 6692
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2023-08-30 10:57:36 +09:00
parent 9dd8fd4ae4
commit 95186ae92f
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054

View File

@ -384,9 +384,6 @@ static int startup_signal_mask_valid;
/* Flag to indicate that a shutdown was requested. */ /* Flag to indicate that a shutdown was requested. */
static int shutdown_pending; static int shutdown_pending;
/* Counter for the currently running own socket checks. */
static int check_own_socket_running;
/* Flags to indicate that check_own_socket shall not be called. */ /* Flags to indicate that check_own_socket shall not be called. */
static int disable_check_own_socket; static int disable_check_own_socket;
@ -396,6 +393,9 @@ static int is_supervised;
/* Flag indicating to start the daemon even if one already runs. */ /* Flag indicating to start the daemon even if one already runs. */
static int steal_socket; static int steal_socket;
/* Flag to monitor socket takeover. */
static int socket_takeover_detected;
/* Flag to inhibit socket removal in cleanup. */ /* Flag to inhibit socket removal in cleanup. */
static int inhibit_socket_removal; static int inhibit_socket_removal;
@ -528,8 +528,8 @@ static void handle_connections (gnupg_fd_t listen_fd,
gnupg_fd_t listen_fd_extra, gnupg_fd_t listen_fd_extra,
gnupg_fd_t listen_fd_browser, gnupg_fd_t listen_fd_browser,
gnupg_fd_t listen_fd_ssh); gnupg_fd_t listen_fd_ssh);
static void check_own_socket (void);
static int check_for_running_agent (int silent); static int check_for_running_agent (int silent);
static void *check_own_socket_thread (void *arg);
/* /*
@ -2442,12 +2442,8 @@ create_directories (void)
static void static void
handle_tick (void) handle_tick (void)
{ {
static time_t last_minute;
struct stat statbuf; struct stat statbuf;
if (!last_minute)
last_minute = time (NULL);
/* If we are running as a child of another process, check whether /* If we are running as a child of another process, check whether
the parent is still alive and shutdown if not. */ the parent is still alive and shutdown if not. */
#ifndef HAVE_W32_SYSTEM #ifndef HAVE_W32_SYSTEM
@ -2464,15 +2460,6 @@ handle_tick (void)
} }
#endif /*HAVE_W32_SYSTEM*/ #endif /*HAVE_W32_SYSTEM*/
/* Code to be run from time to time. */
#if CHECK_OWN_SOCKET_INTERVAL > 0
if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
{
check_own_socket ();
last_minute = time (NULL);
}
#endif
/* Need to check for expired cache entries. */ /* Need to check for expired cache entries. */
agent_cache_housekeeping (); agent_cache_housekeeping ();
@ -3099,6 +3086,15 @@ handle_connections (gnupg_fd_t listen_fd,
else else
have_homedir_inotify = 1; have_homedir_inotify = 1;
if (!disable_check_own_socket)
{
npth_t thread;
err = npth_create (&thread, &tattr, check_own_socket_thread, NULL);
if (err)
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
}
/* On Windows we need to fire up a separate thread to listen for /* On Windows we need to fire up a separate thread to listen for
requests from Putty (an SSH client), so we can replace Putty's requests from Putty (an SSH client), so we can replace Putty's
Pageant (its ssh-agent implementation). */ Pageant (its ssh-agent implementation). */
@ -3278,6 +3274,15 @@ handle_connections (gnupg_fd_t listen_fd,
log_info ("homedir has been removed - shutting down\n"); log_info ("homedir has been removed - shutting down\n");
} }
if (socket_takeover_detected)
{
/* We may not remove the socket as it is now in use by another
server. */
inhibit_socket_removal = 1;
shutdown_pending = 2;
log_info ("this process is useless - shutting down\n");
}
if (!shutdown_pending) if (!shutdown_pending)
{ {
int idx; int idx;
@ -3358,20 +3363,18 @@ check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
} }
/* The thread running the actual check. We need to run this in a /* Check whether we are still listening on our own socket. In case
separate thread so that check_own_thread can be called from the another gpg-agent process started after us has taken ownership of
timer tick. */ our socket, we would linger around without any real task. Thus we
static void * better check once in a while whether we are really needed. */
check_own_socket_thread (void *arg) static int
do_check_own_socket (const char *sockname)
{ {
int rc; int rc;
char *sockname = arg;
assuan_context_t ctx = NULL; assuan_context_t ctx = NULL;
membuf_t mb; membuf_t mb;
char *buffer; char *buffer;
check_own_socket_running++;
rc = assuan_new (&ctx); rc = assuan_new (&ctx);
if (rc) if (rc)
{ {
@ -3409,57 +3412,37 @@ check_own_socket_thread (void *arg)
xfree (buffer); xfree (buffer);
leave: leave:
xfree (sockname);
if (ctx) if (ctx)
assuan_release (ctx); assuan_release (ctx);
if (rc)
{ return rc;
/* We may not remove the socket as it is now in use by another
server. */
inhibit_socket_removal = 1;
shutdown_pending = 2;
log_info ("this process is useless - shutting down\n");
}
check_own_socket_running--;
return NULL;
} }
/* The thread running the actual check. */
/* Check whether we are still listening on our own socket. In case static void *
another gpg-agent process started after us has taken ownership of check_own_socket_thread (void *arg)
our socket, we would linger around without any real task. Thus we
better check once in a while whether we are really needed. */
static void
check_own_socket (void)
{ {
char *sockname; char *sockname;
npth_t thread;
npth_attr_t tattr;
int err;
if (disable_check_own_socket) (void)arg;
return;
if (check_own_socket_running || shutdown_pending)
return; /* Still running or already shutting down. */
sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL); sockname = make_filename_try (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
if (!sockname) if (!sockname)
return; /* Out of memory. */ return NULL; /* Out of memory. */
err = npth_attr_init (&tattr); while (1)
if (err)
{ {
xfree (sockname); if (do_check_own_socket (sockname))
return; break;
}
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
err = npth_create (&thread, &tattr, check_own_socket_thread, sockname);
if (err)
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
npth_attr_destroy (&tattr);
}
gnupg_sleep (CHECK_OWN_SOCKET_INTERVAL);
}
xfree (sockname);
socket_takeover_detected = 1;
return NULL;
}
/* Figure out whether an agent is available and running. Prints an /* Figure out whether an agent is available and running. Prints an