Remove Proc_Kill(), use timeout to kill child processes

This avoids a race and potentionally killing the wrong process on
systems that use randomized process IDs; now the child itself is
responsible to exit in a timely manner using SIGALRM.
This commit is contained in:
Alexander Barton 2010-07-14 10:29:05 +02:00
parent cf93881dfb
commit 6ebb31ab35
5 changed files with 22 additions and 28 deletions

View File

@ -1091,10 +1091,6 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
in_k, out_k); in_k, out_k);
} }
/* Kill possibly running subprocess */
if (Proc_InProgress(&My_Connections[Idx].proc_stat))
Proc_Kill(&My_Connections[Idx].proc_stat);
/* Servers: Modify time of next connect attempt? */ /* Servers: Modify time of next connect attempt? */
Conf_UnsetServer( Idx ); Conf_UnsetServer( Idx );

View File

@ -789,7 +789,10 @@ Hello_User(CLIENT * Client)
return DISCONNECTED; return DISCONNECTED;
} }
pid = Proc_Fork(Conn_GetProcStat(conn), pipefd, cb_Read_Auth_Result); /* Fork child process for PAM authentication; and make sure that the
* process timeout is set higher than the login timeout! */
pid = Proc_Fork(Conn_GetProcStat(conn), pipefd,
cb_Read_Auth_Result, Conf_PongTimeout + 1);
if (pid > 0) { if (pid > 0) {
LogDebug("Authenticator for connection %d created (PID %d).", LogDebug("Authenticator for connection %d created (PID %d).",
conn, pid); conn, pid);

View File

@ -23,6 +23,7 @@
#include "log.h" #include "log.h"
#include "io.h" #include "io.h"
#include "conn.h"
#include "exp.h" #include "exp.h"
#include "proc.h" #include "proc.h"
@ -42,7 +43,7 @@ Proc_InitStruct (PROC_STAT *proc)
* Fork a child process. * Fork a child process.
*/ */
GLOBAL pid_t GLOBAL pid_t
Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short)) Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout)
{ {
pid_t pid; pid_t pid;
@ -67,7 +68,10 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short))
case 0: case 0:
/* New child process: */ /* New child process: */
signal(SIGTERM, Proc_GenericSignalHandler); signal(SIGTERM, Proc_GenericSignalHandler);
signal(SIGALRM, Proc_GenericSignalHandler);
close(pipefds[0]); close(pipefds[0]);
alarm(timeout);
Conn_CloseAllSockets();
return 0; return 0;
} }
@ -87,21 +91,6 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short))
return pid; return pid;
} }
/**
* Kill forked child process.
*/
GLOBAL void
Proc_Kill(PROC_STAT *proc)
{
assert(proc != NULL);
if (proc->pipe_fd > 0)
io_close(proc->pipe_fd);
if (proc->pid > 0)
kill(proc->pid, SIGTERM);
Proc_InitStruct(proc);
}
/** /**
* Generic signal handler for forked child processes. * Generic signal handler for forked child processes.
*/ */
@ -112,6 +101,11 @@ Proc_GenericSignalHandler(int Signal)
case SIGTERM: case SIGTERM:
#ifdef DEBUG #ifdef DEBUG
Log_Subprocess(LOG_DEBUG, "Child got TERM signal, exiting."); Log_Subprocess(LOG_DEBUG, "Child got TERM signal, exiting.");
#endif
exit(1);
case SIGALRM:
#ifdef DEBUG
Log_Subprocess(LOG_DEBUG, "Child got ALARM signal, exiting.");
#endif #endif
exit(1); exit(1);
} }
@ -119,7 +113,7 @@ Proc_GenericSignalHandler(int Signal)
/** /**
* Read bytes from a pipe of a forked child process. * Read bytes from a pipe of a forked child process.
* In addition, this function makes sure that the child process is dead * In addition, this function makes sure that the child process is ignored
* after all data has been read or a fatal error occurred. * after all data has been read or a fatal error occurred.
*/ */
GLOBAL size_t GLOBAL size_t
@ -142,7 +136,7 @@ Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen)
else if (bytes_read == 0) else if (bytes_read == 0)
LogDebug("Can't read from child process %ld: EOF", proc->pid); LogDebug("Can't read from child process %ld: EOF", proc->pid);
#endif #endif
Proc_Kill(proc); Proc_InitStruct(proc);
return (size_t)bytes_read; return (size_t)bytes_read;
} }

View File

@ -26,9 +26,7 @@ typedef struct _Proc_Stat {
GLOBAL void Proc_InitStruct PARAMS((PROC_STAT *proc)); GLOBAL void Proc_InitStruct PARAMS((PROC_STAT *proc));
GLOBAL pid_t Proc_Fork PARAMS((PROC_STAT *proc, int *pipefds, GLOBAL pid_t Proc_Fork PARAMS((PROC_STAT *proc, int *pipefds,
void (*cbfunc)(int, short))); void (*cbfunc)(int, short), int timeout));
GLOBAL void Proc_Kill PARAMS((PROC_STAT *proc));
GLOBAL void Proc_GenericSignalHandler PARAMS((int Signal)); GLOBAL void Proc_GenericSignalHandler PARAMS((int Signal));

View File

@ -12,6 +12,8 @@
*/ */
#define RESOLVER_TIMEOUT (Conf_PongTimeout*3)/4
#include "portab.h" #include "portab.h"
#include "imp.h" #include "imp.h"
@ -33,6 +35,7 @@
#include "array.h" #include "array.h"
#include "conn.h" #include "conn.h"
#include "conf.h"
#include "defines.h" #include "defines.h"
#include "log.h" #include "log.h"
#include "ng_ipaddr.h" #include "ng_ipaddr.h"
@ -63,7 +66,7 @@ Resolve_Addr(PROC_STAT * s, const ng_ipaddr_t *Addr, int identsock,
assert(s != NULL); assert(s != NULL);
pid = Proc_Fork(s, pipefd, cbfunc); pid = Proc_Fork(s, pipefd, cbfunc, RESOLVER_TIMEOUT);
if (pid > 0) { if (pid > 0) {
LogDebug("Resolver for %s created (PID %d).", ng_ipaddr_tostr(Addr), pid); LogDebug("Resolver for %s created (PID %d).", ng_ipaddr_tostr(Addr), pid);
return true; return true;
@ -89,7 +92,7 @@ Resolve_Name( PROC_STAT *s, const char *Host, void (*cbfunc)(int, short))
assert(s != NULL); assert(s != NULL);
pid = Proc_Fork(s, pipefd, cbfunc); pid = Proc_Fork(s, pipefd, cbfunc, RESOLVER_TIMEOUT);
if (pid > 0) { if (pid > 0) {
/* Main process */ /* Main process */
#ifdef DEBUG #ifdef DEBUG