summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2014-08-31 02:21:18 +0000
committerguenther <guenther@openbsd.org>2014-08-31 02:21:18 +0000
commited42a740c17f7bea88482a716bacbc46a06b7249 (patch)
tree41266fb76fcd0cc0229b872cae91df94a24ad430 /lib/libc/gen
parentregen (diff)
downloadwireguard-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.314
-rw-r--r--lib/libc/gen/popen.c57
-rw-r--r--lib/libc/gen/posix_spawn.c15
-rw-r--r--lib/libc/gen/posix_spawn_file_actions_addopen.310
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