sh - Sync to FreeBSD d038ee76 part 2/2 (d)
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 7 Jun 2015 02:44:29 +0000 (19:44 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 7 Jun 2015 02:57:15 +0000 (19:57 -0700)
Reapply 330497ceac - fix O_CLOEXEC race in open() and fhopen()

* Fix an O_CLOEXEC race where a fork/exec can race an open(...O_CLOEXEC)
  and improperly inherit the descriptor.

bin/sh/input.c
bin/sh/jobs.c
bin/sh/main.c
bin/sh/redir.c
bin/sh/shell.h

index 8117e75..8063098 100644 (file)
@@ -368,10 +368,10 @@ setinputfile(const char *fname, int push)
        int fd2;
 
        INTOFF;
-       if ((fd = open(fname, O_RDONLY | O_CLOEXEC)) < 0)
+       if ((fd = open(fname, O_RDONLY | O_CLOEXEC_MAYBE)) < 0)
                error("cannot open %s: %s", fname, strerror(errno));
        if (fd < 10) {
-               fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 10);
+               fd2 = fcntl(fd, F_DUPFD_CLOEXEC_MAYBE, 10);
                close(fd);
                if (fd2 < 0)
                        error("Out of file descriptors");
@@ -390,6 +390,9 @@ setinputfile(const char *fname, int push)
 void
 setinputfd(int fd, int push)
 {
+#if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
+       fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
        if (push) {
                pushfile();
                parsefile->buf = ckmalloc(BUFSIZ + 1);
index 59dc043..a5d97d9 100644 (file)
@@ -146,12 +146,12 @@ setjobctl(int on)
        if (on) {
                if (ttyfd != -1)
                        close(ttyfd);
-               if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
+               if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC_MAYBE)) < 0) {
                        i = 0;
                        while (i <= 2 && !isatty(i))
                                i++;
                        if (i > 2 ||
-                           (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) {
+                           (ttyfd = fcntl(i, F_DUPFD_CLOEXEC_MAYBE, 10)) < 0) {
                                jobctl_notty();
                                return;
                        }
@@ -161,17 +161,24 @@ setjobctl(int on)
                         * Keep our TTY file descriptor out of the way of
                         * the user's redirections.
                         */
-                       if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
+                       if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC_MAYBE, 10)) < 0) {
                                jobctl_notty();
                                return;
                        }
                        close(ttyfd);
                        ttyfd = i;
                }
+#if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
+               if (fcntl(ttyfd, F_SETFD, FD_CLOEXEC) < 0) {
+                       close(ttyfd);
+                       ttyfd = -1;
+                       goto out;
+               }
+#endif
                do { /* while we are in the background */
                        initialpgrp = tcgetpgrp(ttyfd);
                        if (initialpgrp < 0) {
-                               jobctl_notty();
+out:                           jobctl_notty();
                                return;
                        }
                        if (initialpgrp != getpgrp()) {
index c483d19..7f01d2b 100644 (file)
@@ -257,7 +257,7 @@ read_profile(const char *name)
        if (expandedname == NULL)
                return;
        INTOFF;
-       if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC)) >= 0)
+       if ((fd = open(expandedname, O_RDONLY | O_CLOEXEC_MAYBE)) >= 0)
                setinputfd(fd, 1);
        INTON;
        if (fd < 0)
index 674c150..a332723 100644 (file)
@@ -132,7 +132,7 @@ redirect(union node *redir, int flags)
 
                if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
                        INTOFF;
-                       if ((i = fcntl(fd, F_DUPFD_CLOEXEC, 10)) == -1) {
+                       if ((i = fcntl(fd, F_DUPFD_CLOEXEC_MAYBE, 10)) == -1) {
                                switch (errno) {
                                case EBADF:
                                        i = CLOSED;
@@ -143,6 +143,11 @@ redirect(union node *redir, int flags)
                                        break;
                                }
                        }
+#if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
+                       else {
+                               fcntl(i, F_SETFD, FD_CLOEXEC);
+                       }
+#endif
                        sv->renamed[fd] = i;
                        INTON;
                }
index 74f11a3..a628d35 100644 (file)
 #define        JOBS 1
 /* #define DEBUG 1 */
 
+/*
+ * Allow compilation with older versions of DragonFly or on
+ * systems without these features.
+ */
+#ifdef F_DUPFD_CLOEXEC
+#define F_DUPFD_CLOEXEC_MAYBE  F_DUPFD_CLOEXEC
+#else
+#define F_DUPFD_CLOEXEC_MAYBE  F_DUPFD
+#endif
+
+#ifdef O_CLOEXEC
+#define O_CLOEXEC_MAYBE                O_CLOEXEC
+#else
+#define O_CLOEXEC_MAYBE                0
+#endif
+
 /*
  * Type of used arithmetics. SUSv3 requires us to have at least signed long.
  */