diff options
author | 2014-08-31 02:21:18 +0000 | |
---|---|---|
committer | 2014-08-31 02:21:18 +0000 | |
commit | ed42a740c17f7bea88482a716bacbc46a06b7249 (patch) | |
tree | 41266fb76fcd0cc0229b872cae91df94a24ad430 /lib/libc/gen | |
parent | regen (diff) | |
download | wireguard-openbsd-ed42a740c17f7bea88482a716bacbc46a06b7249.tar.xz wireguard-openbsd-ed42a740c17f7bea88482a716bacbc46a06b7249.zip |
Add additional userland interfaces for setting close-on-exec on fds
when creating them: mkostemp(), mkostemps(), the 'e' mode letter for
fopen(), freopen(), fdopen(), and popen(). The close-on-exec flag will
be cleared by the action created by posix_spawn_file_actions_adddup2().
Also, add support for the C11 'x' mode letter for fopen() and freopen(),
setting O_EXCL when possibly creating files.
Note: this requires kernel support for pipe2() and dup3()!
ok millert@
Diffstat (limited to 'lib/libc/gen')
-rw-r--r-- | lib/libc/gen/popen.3 | 14 | ||||
-rw-r--r-- | lib/libc/gen/popen.c | 57 | ||||
-rw-r--r-- | lib/libc/gen/posix_spawn.c | 15 | ||||
-rw-r--r-- | lib/libc/gen/posix_spawn_file_actions_addopen.3 | 10 |
4 files changed, 61 insertions, 35 deletions
diff --git a/lib/libc/gen/popen.3 b/lib/libc/gen/popen.3 index dfadbd7f8c8..ba1b8cfc47f 100644 --- a/lib/libc/gen/popen.3 +++ b/lib/libc/gen/popen.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: popen.3,v 1.18 2014/01/19 10:39:00 schwarze Exp $ +.\" $OpenBSD: popen.3,v 1.19 2014/08/31 02:21:18 guenther Exp $ .\" .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: January 19 2014 $ +.Dd $Mdocdate: August 31 2014 $ .Dt POPEN 3 .Os .Sh NAME @@ -65,10 +65,20 @@ The argument is a pointer to a NUL-terminated string which must be either .Qq r +or +.Qq re for reading or .Qq w +or +.Qq we for writing. +If the letter +.Qq e +is present in the string then the close-on-exec flag shall be set on the +file descriptor underlying the +.Vt FILE +that is returned. .Pp The return value from .Fn popen diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c index d7c6c61731f..973291d2dc8 100644 --- a/lib/libc/gen/popen.c +++ b/lib/libc/gen/popen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: popen.c,v 1.18 2007/11/26 19:26:46 kurt Exp $ */ +/* $OpenBSD: popen.c,v 1.19 2014/08/31 02:21:18 guenther Exp $ */ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. @@ -36,11 +36,13 @@ #include <signal.h> #include <errno.h> +#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <paths.h> +#include <wchar.h> #include "thread_private.h" static struct pid { @@ -57,9 +59,11 @@ popen(const char *program, const char *type) struct pid * volatile cur; FILE *iop; int pdes[2]; + int target; pid_t pid; - if ((*type != 'r' && *type != 'w') || type[1] != '\0') { + if ((*type != 'r' && *type != 'w') || + (type[1] != '\0' && (type[1] != 'e' || type[2] != '\0'))) { errno = EINVAL; return (NULL); } @@ -67,7 +71,7 @@ popen(const char *program, const char *type) if ((cur = malloc(sizeof(struct pid))) == NULL) return (NULL); - if (pipe(pdes) < 0) { + if (pipe2(pdes, O_CLOEXEC) < 0) { free(cur); return (NULL); } @@ -84,6 +88,7 @@ popen(const char *program, const char *type) case 0: /* Child. */ { struct pid *pcur; + /* * because vfork() instead of fork(), must leak FILE *, * but luckily we are terminally headed for an execl() @@ -91,26 +96,18 @@ popen(const char *program, const char *type) for (pcur = pidlist; pcur; pcur = pcur->next) close(fileno(pcur->fp)); - if (*type == 'r') { - int tpdes1 = pdes[1]; - - (void) close(pdes[0]); - /* - * We must NOT modify pdes, due to the - * semantics of vfork. - */ - if (tpdes1 != STDOUT_FILENO) { - (void)dup2(tpdes1, STDOUT_FILENO); - (void)close(tpdes1); - tpdes1 = STDOUT_FILENO; - } + target = *type == 'r'; + if (pdes[target] != target) { + if (dup2(pdes[target], target) == -1) + _exit(127); } else { - (void)close(pdes[1]); - if (pdes[0] != STDIN_FILENO) { - (void)dup2(pdes[0], STDIN_FILENO); - (void)close(pdes[0]); - } + int flags = fcntl(pdes[target], F_GETFD); + if (flags == -1 || ((flags & FD_CLOEXEC) && + fcntl(pdes[target], F_SETFD, flags & ~FD_CLOEXEC) + == -1)) + _exit(127); } + execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL); _exit(127); /* NOTREACHED */ @@ -119,13 +116,10 @@ popen(const char *program, const char *type) _MUTEX_UNLOCK(&pidlist_lock); /* Parent; assume fdopen can't fail. */ - if (*type == 'r') { - iop = fdopen(pdes[0], type); - (void)close(pdes[1]); - } else { - iop = fdopen(pdes[1], type); - (void)close(pdes[0]); - } + target = *type == 'w'; + iop = fdopen(pdes[target], type); + fwide(iop, -1); + (void)close(pdes[!target]); /* Link into list of file descriptors. */ cur->fp = iop; @@ -135,6 +129,13 @@ popen(const char *program, const char *type) pidlist = cur; _MUTEX_UNLOCK(&pidlist_lock); + /* now that it's in the list, clear FD_CLOEXEC if unwanted */ + if (type[1] != 'e') { + int flags = fcntl(pdes[target], F_GETFD); + if (flags != -1) + fcntl(pdes[target], F_SETFD, flags & ~FD_CLOEXEC); + } + return (iop); } diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c index acfe68c63c5..c45080b1a11 100644 --- a/lib/libc/gen/posix_spawn.c +++ b/lib/libc/gen/posix_spawn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: posix_spawn.c,v 1.3 2012/12/05 23:20:00 deraadt Exp $ */ +/* $OpenBSD: posix_spawn.c,v 1.4 2014/08/31 02:21:18 guenther Exp $ */ /*- * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> * All rights reserved. @@ -155,8 +155,17 @@ process_file_actions_entry(posix_spawn_file_actions_entry_t *fae) } break; case FAE_DUP2: - /* Perform a dup2() */ - if (dup2(fae->fae_fildes, fae->fae_newfildes) == -1) + /* + * Perform a dup2(), making sure the FD_CLOEXEC flag is clear + */ + if (fae->fae_fildes == fae->fae_newfildes) { + int flags = fcntl(fd, F_GETFD); + + if (flags == -1 || + ((flags & FD_CLOEXEC) && + fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) == -1)) + return (errno); + } else if (dup2(fae->fae_fildes, fae->fae_newfildes) == -1) return (errno); break; case FAE_CLOSE: diff --git a/lib/libc/gen/posix_spawn_file_actions_addopen.3 b/lib/libc/gen/posix_spawn_file_actions_addopen.3 index 519a9a6f92f..b00ee325e8c 100644 --- a/lib/libc/gen/posix_spawn_file_actions_addopen.3 +++ b/lib/libc/gen/posix_spawn_file_actions_addopen.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: posix_spawn_file_actions_addopen.3,v 1.6 2013/07/16 15:21:11 schwarze Exp $ +.\" $OpenBSD: posix_spawn_file_actions_addopen.3,v 1.7 2014/08/31 02:21:18 guenther Exp $ .\" .\" Copyright (c) 2012 Marc Espie <espie@openbsd.org> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 16 2013 $ +.Dd $Mdocdate: August 31 2014 $ .Dt POSIX_SPAWN_FILE_ACTIONS_ADDOPEN 3 .Os .Sh NAME @@ -61,6 +61,12 @@ dup2(fildes, newfildes); .Ed .Pp to be called. +In addition, the action will cause the close-on-exec flag to be cleared on +.Fa newfildes , +even if +.Fa newfildes +equals +.Fa fildes . .It The .Fn posix_spawn_file_actions_addopen |