winpr: fix CreateProcess signal handler issues
The calling thread of CreateProcess can be in any library and can have arbitrary signal masks and handlers. We now save the caller's mask and block all signals before forking. After fork: - child resets the handlers and unblocks all signals. - parent restores the caller's original signal mask.
This commit is contained in:
parent
873a25621d
commit
c84e90bf06
@ -80,6 +80,14 @@
|
|||||||
#include "../handle/handle.h"
|
#include "../handle/handle.h"
|
||||||
#include "../security/security.h"
|
#include "../security/security.h"
|
||||||
|
|
||||||
|
#ifndef NSIG
|
||||||
|
#ifdef SIGMAX
|
||||||
|
#define NSIG SIGMAX
|
||||||
|
#else
|
||||||
|
#define NSIG 64
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
|
char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
|
||||||
{
|
{
|
||||||
char* p;
|
char* p;
|
||||||
@ -210,6 +218,9 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
|||||||
WINPR_ACCESS_TOKEN* token;
|
WINPR_ACCESS_TOKEN* token;
|
||||||
LPTCH lpszEnvironmentBlock;
|
LPTCH lpszEnvironmentBlock;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
sigset_t oldSigMask;
|
||||||
|
sigset_t newSigMask;
|
||||||
|
BOOL restoreSigMask = FALSE;
|
||||||
|
|
||||||
pid = 0;
|
pid = 0;
|
||||||
numArgs = 0;
|
numArgs = 0;
|
||||||
@ -241,6 +252,10 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
|||||||
if (NULL == filename)
|
if (NULL == filename)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
|
/* block all signals so that the child can safely reset the caller's handlers */
|
||||||
|
sigfillset(&newSigMask);
|
||||||
|
restoreSigMask = !pthread_sigmask(SIG_SETMASK, &newSigMask, &oldSigMask);
|
||||||
|
|
||||||
/* fork and exec */
|
/* fork and exec */
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@ -254,16 +269,33 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
|||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
{
|
{
|
||||||
/* child process */
|
/* child process */
|
||||||
|
#ifndef __sun
|
||||||
|
int maxfd;
|
||||||
|
#endif
|
||||||
|
int fd;
|
||||||
|
int sig;
|
||||||
|
sigset_t set;
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
/* set default signal handlers */
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
act.sa_sigaction = SIG_DFL;
|
||||||
|
act.sa_flags = 0;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
for (sig = 1; sig < NSIG; sig++)
|
||||||
|
sigaction(sig, &act, NULL);
|
||||||
|
/* unblock all signals */
|
||||||
|
sigfillset(&set);
|
||||||
|
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||||
|
|
||||||
#ifdef __sun
|
#ifdef __sun
|
||||||
closefrom(3);
|
closefrom(3);
|
||||||
#else
|
#else
|
||||||
int maxfd;
|
|
||||||
#ifdef F_MAXFD // on some BSD derivates
|
#ifdef F_MAXFD // on some BSD derivates
|
||||||
maxfd = fcntl(0, F_MAXFD);
|
maxfd = fcntl(0, F_MAXFD);
|
||||||
#else
|
#else
|
||||||
maxfd = sysconf(_SC_OPEN_MAX);
|
maxfd = sysconf(_SC_OPEN_MAX);
|
||||||
#endif
|
#endif
|
||||||
int fd;
|
|
||||||
for(fd=3; fd<maxfd; fd++)
|
for(fd=3; fd<maxfd; fd++)
|
||||||
close(fd);
|
close(fd);
|
||||||
#endif // __sun
|
#endif // __sun
|
||||||
@ -324,6 +356,12 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
|||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
|
||||||
|
/* restore caller's original signal mask */
|
||||||
|
if (restoreSigMask)
|
||||||
|
pthread_sigmask(SIG_SETMASK, &oldSigMask, NULL);
|
||||||
|
|
||||||
|
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
if (pArgs)
|
if (pArgs)
|
||||||
|
Loading…
Reference in New Issue
Block a user