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
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
||||
#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 /* LIBC_SCCS and not lint */
|
||||
|
||||
|
@ -54,18 +54,13 @@ __weak_alias(execl,_execl)
|
|||
|
||||
|
||||
extern char **environ;
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t __environ_lock;
|
||||
#endif
|
||||
|
||||
int
|
||||
execl(const char *name, const char *arg, ...)
|
||||
{
|
||||
int r;
|
||||
#if defined(__i386__) || defined(__m68k__) || defined(__ns32k__)
|
||||
rwlock_rdlock(&__environ_lock);
|
||||
r = execve(name, (char **) &arg, environ);
|
||||
rwlock_unlock(&__environ_lock);
|
||||
return (r);
|
||||
#else
|
||||
va_list ap;
|
||||
|
@ -85,9 +80,7 @@ execl(const char *name, const char *arg, ...)
|
|||
;
|
||||
va_end(ap);
|
||||
|
||||
rwlock_rdlock(&__environ_lock);
|
||||
r = execve(name, argv, environ);
|
||||
rwlock_unlock(&__environ_lock);
|
||||
return (r);
|
||||
#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
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
||||
#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 /* LIBC_SCCS and not lint */
|
||||
|
||||
|
@ -51,9 +51,6 @@ __weak_alias(execv,_execv)
|
|||
#endif
|
||||
|
||||
extern char **environ;
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t __environ_lock;
|
||||
#endif
|
||||
|
||||
int
|
||||
execv(name, argv)
|
||||
|
@ -62,8 +59,6 @@ execv(name, argv)
|
|||
{
|
||||
int r;
|
||||
|
||||
rwlock_rdlock(&__environ_lock);
|
||||
r = execve(name, argv, environ);
|
||||
rwlock_unlock(&__environ_lock);
|
||||
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
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
|
||||
#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 /* LIBC_SCCS and not lint */
|
||||
|
||||
|
@ -58,9 +58,6 @@ __weak_alias(execvp,_execvp)
|
|||
#endif
|
||||
|
||||
extern char **environ;
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t __environ_lock;
|
||||
#endif
|
||||
|
||||
int
|
||||
execvp(const char *name, char * const *argv)
|
||||
|
@ -123,9 +120,7 @@ execvp(const char *name, char * const *argv)
|
|||
memcpy(buf + lp + 1, name, ln);
|
||||
buf[lp + ln + 1] = '\0';
|
||||
|
||||
retry: rwlock_rdlock(&__environ_lock);
|
||||
(void)execve(bp, argv, environ);
|
||||
rwlock_unlock(&__environ_lock);
|
||||
retry: (void)execve(bp, argv, environ);
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
eacces = 1;
|
||||
|
@ -140,10 +135,8 @@ retry: rwlock_rdlock(&__environ_lock);
|
|||
memp[0] = _PATH_BSHELL;
|
||||
memp[1] = bp;
|
||||
(void)memcpy(&memp[2], &argv[1], cnt * sizeof(*memp));
|
||||
rwlock_rdlock(&__environ_lock);
|
||||
(void)execve(_PATH_BSHELL, (char * const *)memp,
|
||||
environ);
|
||||
rwlock_unlock(&__environ_lock);
|
||||
goto done;
|
||||
case ETXTBSY:
|
||||
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
|
||||
|
@ -41,7 +41,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
|
||||
#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 /* 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 <string.h>
|
||||
#include <unistd.h>
|
||||
#include "reentrant.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(popen,_popen)
|
||||
__weak_alias(pclose,_pclose)
|
||||
#endif
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t __environ_lock;
|
||||
#endif
|
||||
|
||||
static struct pid {
|
||||
struct pid *next;
|
||||
FILE *fp;
|
||||
|
@ -107,9 +112,11 @@ popen(command, type)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
rwlock_rdlock(&__environ_lock);
|
||||
switch (pid = vfork()) {
|
||||
case -1: /* Error. */
|
||||
serrno = errno;
|
||||
rwlock_unlock(&__environ_lock);
|
||||
free(cur);
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
|
@ -143,6 +150,7 @@ popen(command, type)
|
|||
_exit(127);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
rwlock_unlock(&__environ_lock);
|
||||
|
||||
/* Parent; assume fdopen can't fail. */
|
||||
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
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
|
||||
#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 /* 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 <unistd.h>
|
||||
#include <paths.h>
|
||||
#include "reentrant.h"
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t __environ_lock;
|
||||
#endif
|
||||
extern char **environ;
|
||||
|
||||
int
|
||||
|
@ -80,8 +84,10 @@ system(command)
|
|||
if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)
|
||||
return -1;
|
||||
|
||||
rwlock_rdlock(&__environ_lock);
|
||||
switch(pid = vfork()) {
|
||||
case -1: /* error */
|
||||
rwlock_unlock(&__environ_lock);
|
||||
sigaction(SIGINT, &intsa, NULL);
|
||||
sigaction(SIGQUIT, &quitsa, NULL);
|
||||
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
|
@ -93,6 +99,7 @@ system(command)
|
|||
execve(_PATH_BSHELL, argp, environ);
|
||||
_exit(127);
|
||||
}
|
||||
rwlock_unlock(&__environ_lock);
|
||||
|
||||
while (waitpid(pid, &pstat, 0) == -1) {
|
||||
if (errno != EINTR) {
|
||||
|
|
Loading…
Reference in New Issue