mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-12 15:52:55 +00:00
Avoid signal race in virExec
This commit is contained in:
parent
f2172946e5
commit
60ed1d2a7a
@ -1,3 +1,12 @@
|
|||||||
|
Wed Aug 20 09:35:33 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
Avoid signal race in virExec()
|
||||||
|
* src/util.c: Block signals when forking and clear child's
|
||||||
|
signal handlers.
|
||||||
|
* src/remote_protocol.{c,h,x}: Add config.h include file
|
||||||
|
* src/internal.h: define pthread_sigmask interms of sigprocmask
|
||||||
|
for non-pthreads systems
|
||||||
|
|
||||||
Wed Aug 20 09:28:33 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
Wed Aug 20 09:28:33 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
* src/util.c: Re-arrange virExec() to improve error reporting
|
* src/util.c: Re-arrange virExec() to improve error reporting
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "remote_protocol.h"
|
#include "remote_protocol.h"
|
||||||
|
#include <config.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
bool_t
|
bool_t
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#define REMOTE_MESSAGE_MAX 262144
|
#define REMOTE_MESSAGE_MAX 262144
|
||||||
#define REMOTE_STRING_MAX 65536
|
#define REMOTE_STRING_MAX 65536
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
* 'REMOTE_'. This makes names quite long.
|
* 'REMOTE_'. This makes names quite long.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
%#include <config.h>
|
||||||
%#include "internal.h"
|
%#include "internal.h"
|
||||||
|
|
||||||
/*----- Data types. -----*/
|
/*----- Data types. -----*/
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define pthread_mutex_destroy(lk) /*empty*/
|
#define pthread_mutex_destroy(lk) /*empty*/
|
||||||
#define pthread_mutex_lock(lk) /*empty*/
|
#define pthread_mutex_lock(lk) /*empty*/
|
||||||
#define pthread_mutex_unlock(lk) /*empty*/
|
#define pthread_mutex_unlock(lk) /*empty*/
|
||||||
|
#define pthread_sigmask(h, s, o) sigprocmask((h), (s), (o))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The library itself is allowed to use deprecated functions /
|
/* The library itself is allowed to use deprecated functions /
|
||||||
|
55
src/util.c
55
src/util.c
@ -37,6 +37,7 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#endif
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#if HAVE_TERMIOS_H
|
#if HAVE_TERMIOS_H
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
@ -53,6 +54,10 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "util-lib.c"
|
#include "util-lib.c"
|
||||||
|
|
||||||
|
#ifndef NSIG
|
||||||
|
# define NSIG 32
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
# define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
@ -110,9 +115,23 @@ static int
|
|||||||
_virExec(virConnectPtr conn,
|
_virExec(virConnectPtr conn,
|
||||||
const char *const*argv,
|
const char *const*argv,
|
||||||
int *retpid, int infd, int *outfd, int *errfd, int non_block) {
|
int *retpid, int infd, int *outfd, int *errfd, int non_block) {
|
||||||
int pid, null;
|
int pid, null, i;
|
||||||
int pipeout[2] = {-1,-1};
|
int pipeout[2] = {-1,-1};
|
||||||
int pipeerr[2] = {-1,-1};
|
int pipeerr[2] = {-1,-1};
|
||||||
|
sigset_t oldmask, newmask;
|
||||||
|
struct sigaction sig_action;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to block signals now, so that child process can safely
|
||||||
|
* kill off caller's signal handlers without a race.
|
||||||
|
*/
|
||||||
|
sigfillset(&newmask);
|
||||||
|
if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
|
||||||
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot block signals: %s"),
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
|
if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
|
||||||
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -172,6 +191,16 @@ _virExec(virConnectPtr conn,
|
|||||||
close(pipeerr[1]);
|
close(pipeerr[1]);
|
||||||
*errfd = pipeerr[0];
|
*errfd = pipeerr[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Restore our original signal mask now child is safely
|
||||||
|
running */
|
||||||
|
if (pthread_sigmask(SIG_SETMASK, &oldmask, NULL) != 0) {
|
||||||
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot unblock signals: %s"),
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
*retpid = pid;
|
*retpid = pid;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -186,6 +215,30 @@ _virExec(virConnectPtr conn,
|
|||||||
of being seen / logged */
|
of being seen / logged */
|
||||||
virSetErrorFunc(NULL, NULL);
|
virSetErrorFunc(NULL, NULL);
|
||||||
|
|
||||||
|
/* Clear out all signal handlers from parent so nothing
|
||||||
|
unexpected can happen in our child once we unblock
|
||||||
|
signals */
|
||||||
|
sig_action.sa_handler = SIG_DFL;
|
||||||
|
sig_action.sa_flags = 0;
|
||||||
|
sigemptyset(&sig_action.sa_mask);
|
||||||
|
|
||||||
|
for (i = 1 ; i < NSIG ; i++)
|
||||||
|
/* Only possible errors are EFAULT or EINVAL
|
||||||
|
The former wont happen, the latter we
|
||||||
|
expect, so no need to check return value */
|
||||||
|
sigaction(i, &sig_action, NULL);
|
||||||
|
|
||||||
|
/* Unmask all signals in child, since we've no idea
|
||||||
|
what the caller's done with their signal mask
|
||||||
|
and don't want to propagate that to children */
|
||||||
|
sigemptyset(&newmask);
|
||||||
|
if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
|
||||||
|
ReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot unblock signals: %s"),
|
||||||
|
strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (pipeout[0] > 0)
|
if (pipeout[0] > 0)
|
||||||
close(pipeout[0]);
|
close(pipeout[0]);
|
||||||
if (pipeerr[0] > 0)
|
if (pipeerr[0] > 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user