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:
nathanw 2003-03-04 19:44:09 +00:00
parent 2ea5d53fe3
commit f60f35f3ab
5 changed files with 26 additions and 30 deletions

View File

@ -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
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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') {

View File

@ -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) {