Don't acquire __environ_lock around exec*() calls; nothing requires
that these calls be thread-safe with respect to the environment, and it causes serious problems for threaded applications which call vfork() and exec*() (including indirectly, via popen() or system()). Acquire and release __environ_lock in the parent in popen() and system() to play safe and provide the child with a stable environment. __environ_lock should also have an atfork() handler; still under development.
This commit is contained in:
parent
2ea5d53fe3
commit
f60f35f3ab
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: execl.c,v 1.9 2003/01/18 11:23:53 thorpej Exp $ */
|
/* $NetBSD: execl.c,v 1.10 2003/03/04 19:44:09 nathanw Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: execl.c,v 1.9 2003/01/18 11:23:53 thorpej Exp $");
|
__RCSID("$NetBSD: execl.c,v 1.10 2003/03/04 19:44:09 nathanw Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* LIBC_SCCS and not lint */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
@ -54,18 +54,13 @@ __weak_alias(execl,_execl)
|
||||||
|
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
#ifdef _REENTRANT
|
|
||||||
extern rwlock_t __environ_lock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
execl(const char *name, const char *arg, ...)
|
execl(const char *name, const char *arg, ...)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
#if defined(__i386__) || defined(__m68k__) || defined(__ns32k__)
|
#if defined(__i386__) || defined(__m68k__) || defined(__ns32k__)
|
||||||
rwlock_rdlock(&__environ_lock);
|
|
||||||
r = execve(name, (char **) &arg, environ);
|
r = execve(name, (char **) &arg, environ);
|
||||||
rwlock_unlock(&__environ_lock);
|
|
||||||
return (r);
|
return (r);
|
||||||
#else
|
#else
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -85,9 +80,7 @@ execl(const char *name, const char *arg, ...)
|
||||||
;
|
;
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
rwlock_rdlock(&__environ_lock);
|
|
||||||
r = execve(name, argv, environ);
|
r = execve(name, argv, environ);
|
||||||
rwlock_unlock(&__environ_lock);
|
|
||||||
return (r);
|
return (r);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: execv.c,v 1.6 2003/01/18 11:23:53 thorpej Exp $ */
|
/* $NetBSD: execv.c,v 1.7 2003/03/04 19:44:09 nathanw Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: execv.c,v 1.6 2003/01/18 11:23:53 thorpej Exp $");
|
__RCSID("$NetBSD: execv.c,v 1.7 2003/03/04 19:44:09 nathanw Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* LIBC_SCCS and not lint */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
@ -51,9 +51,6 @@ __weak_alias(execv,_execv)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
#ifdef _REENTRANT
|
|
||||||
extern rwlock_t __environ_lock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
execv(name, argv)
|
execv(name, argv)
|
||||||
|
@ -62,8 +59,6 @@ execv(name, argv)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
rwlock_rdlock(&__environ_lock);
|
|
||||||
r = execve(name, argv, environ);
|
r = execve(name, argv, environ);
|
||||||
rwlock_unlock(&__environ_lock);
|
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: execvp.c,v 1.21 2003/01/18 11:23:53 thorpej Exp $ */
|
/* $NetBSD: execvp.c,v 1.22 2003/03/04 19:44:10 nathanw Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: execvp.c,v 1.21 2003/01/18 11:23:53 thorpej Exp $");
|
__RCSID("$NetBSD: execvp.c,v 1.22 2003/03/04 19:44:10 nathanw Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* LIBC_SCCS and not lint */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
@ -58,9 +58,6 @@ __weak_alias(execvp,_execvp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
#ifdef _REENTRANT
|
|
||||||
extern rwlock_t __environ_lock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
execvp(const char *name, char * const *argv)
|
execvp(const char *name, char * const *argv)
|
||||||
|
@ -123,9 +120,7 @@ execvp(const char *name, char * const *argv)
|
||||||
memcpy(buf + lp + 1, name, ln);
|
memcpy(buf + lp + 1, name, ln);
|
||||||
buf[lp + ln + 1] = '\0';
|
buf[lp + ln + 1] = '\0';
|
||||||
|
|
||||||
retry: rwlock_rdlock(&__environ_lock);
|
retry: (void)execve(bp, argv, environ);
|
||||||
(void)execve(bp, argv, environ);
|
|
||||||
rwlock_unlock(&__environ_lock);
|
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EACCES:
|
case EACCES:
|
||||||
eacces = 1;
|
eacces = 1;
|
||||||
|
@ -140,10 +135,8 @@ retry: rwlock_rdlock(&__environ_lock);
|
||||||
memp[0] = _PATH_BSHELL;
|
memp[0] = _PATH_BSHELL;
|
||||||
memp[1] = bp;
|
memp[1] = bp;
|
||||||
(void)memcpy(&memp[2], &argv[1], cnt * sizeof(*memp));
|
(void)memcpy(&memp[2], &argv[1], cnt * sizeof(*memp));
|
||||||
rwlock_rdlock(&__environ_lock);
|
|
||||||
(void)execve(_PATH_BSHELL, (char * const *)memp,
|
(void)execve(_PATH_BSHELL, (char * const *)memp,
|
||||||
environ);
|
environ);
|
||||||
rwlock_unlock(&__environ_lock);
|
|
||||||
goto done;
|
goto done;
|
||||||
case ETXTBSY:
|
case ETXTBSY:
|
||||||
if (etxtbsy < 3)
|
if (etxtbsy < 3)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: popen.c,v 1.25 2000/01/22 22:19:11 mycroft Exp $ */
|
/* $NetBSD: popen.c,v 1.26 2003/03/04 19:44:10 nathanw Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1993
|
* Copyright (c) 1988, 1993
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
|
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: popen.c,v 1.25 2000/01/22 22:19:11 mycroft Exp $");
|
__RCSID("$NetBSD: popen.c,v 1.26 2003/03/04 19:44:10 nathanw Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* LIBC_SCCS and not lint */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
@ -58,12 +58,17 @@ __RCSID("$NetBSD: popen.c,v 1.25 2000/01/22 22:19:11 mycroft Exp $");
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "reentrant.h"
|
||||||
|
|
||||||
#ifdef __weak_alias
|
#ifdef __weak_alias
|
||||||
__weak_alias(popen,_popen)
|
__weak_alias(popen,_popen)
|
||||||
__weak_alias(pclose,_pclose)
|
__weak_alias(pclose,_pclose)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
extern rwlock_t __environ_lock;
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct pid {
|
static struct pid {
|
||||||
struct pid *next;
|
struct pid *next;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -107,9 +112,11 @@ popen(command, type)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rwlock_rdlock(&__environ_lock);
|
||||||
switch (pid = vfork()) {
|
switch (pid = vfork()) {
|
||||||
case -1: /* Error. */
|
case -1: /* Error. */
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
|
rwlock_unlock(&__environ_lock);
|
||||||
free(cur);
|
free(cur);
|
||||||
(void)close(pdes[0]);
|
(void)close(pdes[0]);
|
||||||
(void)close(pdes[1]);
|
(void)close(pdes[1]);
|
||||||
|
@ -143,6 +150,7 @@ popen(command, type)
|
||||||
_exit(127);
|
_exit(127);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
rwlock_unlock(&__environ_lock);
|
||||||
|
|
||||||
/* Parent; assume fdopen can't fail. */
|
/* Parent; assume fdopen can't fail. */
|
||||||
if (*type == 'r') {
|
if (*type == 'r') {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: system.c,v 1.17 2001/10/31 13:31:26 kleink Exp $ */
|
/* $NetBSD: system.c,v 1.18 2003/03/04 19:44:10 nathanw Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1993
|
* Copyright (c) 1988, 1993
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
|
static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: system.c,v 1.17 2001/10/31 13:31:26 kleink Exp $");
|
__RCSID("$NetBSD: system.c,v 1.18 2003/03/04 19:44:10 nathanw Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* LIBC_SCCS and not lint */
|
#endif /* LIBC_SCCS and not lint */
|
||||||
|
|
||||||
|
@ -50,7 +50,11 @@ __RCSID("$NetBSD: system.c,v 1.17 2001/10/31 13:31:26 kleink Exp $");
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
|
#include "reentrant.h"
|
||||||
|
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
extern rwlock_t __environ_lock;
|
||||||
|
#endif
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -80,8 +84,10 @@ system(command)
|
||||||
if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)
|
if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
rwlock_rdlock(&__environ_lock);
|
||||||
switch(pid = vfork()) {
|
switch(pid = vfork()) {
|
||||||
case -1: /* error */
|
case -1: /* error */
|
||||||
|
rwlock_unlock(&__environ_lock);
|
||||||
sigaction(SIGINT, &intsa, NULL);
|
sigaction(SIGINT, &intsa, NULL);
|
||||||
sigaction(SIGQUIT, &quitsa, NULL);
|
sigaction(SIGQUIT, &quitsa, NULL);
|
||||||
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
|
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
@ -93,6 +99,7 @@ system(command)
|
||||||
execve(_PATH_BSHELL, argp, environ);
|
execve(_PATH_BSHELL, argp, environ);
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
|
rwlock_unlock(&__environ_lock);
|
||||||
|
|
||||||
while (waitpid(pid, &pstat, 0) == -1) {
|
while (waitpid(pid, &pstat, 0) == -1) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
|
|
Loading…
Reference in New Issue