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);
}
/* 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? */
Conf_UnsetServer( Idx );

View File

@ -789,7 +789,10 @@ Hello_User(CLIENT * Client)
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) {
LogDebug("Authenticator for connection %d created (PID %d).",
conn, pid);

View File

@ -23,6 +23,7 @@
#include "log.h"
#include "io.h"
#include "conn.h"
#include "exp.h"
#include "proc.h"
@ -42,7 +43,7 @@ Proc_InitStruct (PROC_STAT *proc)
* Fork a child process.
*/
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;
@ -67,7 +68,10 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short))
case 0:
/* New child process: */
signal(SIGTERM, Proc_GenericSignalHandler);
signal(SIGALRM, Proc_GenericSignalHandler);
close(pipefds[0]);
alarm(timeout);
Conn_CloseAllSockets();
return 0;
}
@ -87,21 +91,6 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short))
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.
*/
@ -112,6 +101,11 @@ Proc_GenericSignalHandler(int Signal)
case SIGTERM:
#ifdef DEBUG
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
exit(1);
}
@ -119,7 +113,7 @@ Proc_GenericSignalHandler(int Signal)
/**
* 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.
*/
GLOBAL size_t
@ -142,7 +136,7 @@ Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen)
else if (bytes_read == 0)
LogDebug("Can't read from child process %ld: EOF", proc->pid);
#endif
Proc_Kill(proc);
Proc_InitStruct(proc);
return (size_t)bytes_read;
}

View File

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

View File

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