Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

src: Pull up following revision(s) (requested by christos in tic...



details:   https://anonhg.NetBSD.org/src/rev/5dc249a5ef65
branches:  netbsd-8
changeset: 318083:5dc249a5ef65
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Apr 12 01:45:57 2018 +0000
description:
Pull up following revision(s) (requested by christos in ticket #741):
        lib/libc/stdio/flags.c: revision 1.19
        lib/libc/stdio/fdopen.c: revision 1.18
        sys/kern/vfs_vnops.c: revision 1.196
        lib/libc/stdio/freopen.c: revision 1.20
        lib/libc/stdio/fopen.c: revision 1.17
        external/bsd/nvi/dist/common/recover.c: revision 1.10
        external/bsd/nvi/dist/common/recover.c: revision 1.11
        lib/libc/sys/open.2: revision 1.58
        sys/sys/fcntl.h: revision 1.49
make the checkok test stricter to avoid races, and use O_REGULAR.
Instead of opening the file and using popen(3), pass the file descriptor
to sendmail directory. Idea and code from Todd Miller.
Add O_REGULAR to enforce opening of only regular files
(like we have O_DIRECTORY for directories).
This is better than open(, O_NONBLOCK), fstat()+S_ISREG() because opening
devices can have side effects.

diffstat:

 external/bsd/nvi/dist/common/recover.c |  72 ++++++++++++++++++---------------
 lib/libc/stdio/fdopen.c                |   6 +-
 lib/libc/stdio/flags.c                 |   6 +-
 lib/libc/stdio/fopen.c                 |  18 +-------
 lib/libc/stdio/freopen.c               |  19 +--------
 lib/libc/sys/open.2                    |   6 +-
 sys/kern/vfs_vnops.c                   |   7 ++-
 sys/sys/fcntl.h                        |   5 +-
 8 files changed, 61 insertions(+), 78 deletions(-)

diffs (truncated from 367 to 300 lines):

diff -r bbcdb3933cc5 -r 5dc249a5ef65 external/bsd/nvi/dist/common/recover.c
--- a/external/bsd/nvi/dist/common/recover.c    Thu Apr 12 01:38:42 2018 +0000
+++ b/external/bsd/nvi/dist/common/recover.c    Thu Apr 12 01:45:57 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: recover.c,v 1.5.22.1 2017/11/06 09:37:24 snj Exp $ */
+/*     $NetBSD: recover.c,v 1.5.22.2 2018/04/12 01:45:57 msaitoh Exp $ */
 /*-
  * Copyright (c) 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
@@ -16,12 +16,13 @@
 static const char sccsid[] = "Id: recover.c,v 10.31 2001/11/01 15:24:44 skimo Exp  (Berkeley) Date: 2001/11/01 15:24:44 ";
 #endif /* not lint */
 #else
-__RCSID("$NetBSD: recover.c,v 1.5.22.1 2017/11/06 09:37:24 snj Exp $");
+__RCSID("$NetBSD: recover.c,v 1.5.22.2 2018/04/12 01:45:57 msaitoh Exp $");
 #endif
 
 #include <sys/param.h>
 #include <sys/types.h>         /* XXX: param.h may not have included types.h */
 #include <sys/queue.h>
+#include <sys/wait.h>
 #include <sys/stat.h>
 
 /*
@@ -116,11 +117,15 @@
 #define        VI_PHEADER      "X-vi-recover-path: "
 
 static int      rcv_copy(SCR *, int, char *);
-static void     rcv_email(SCR *, const char *);
+static void     rcv_email(SCR *, int fd);
 static char    *rcv_gets(char *, size_t, int);
 static int      rcv_mailfile(SCR *, int, char *);
 static int      rcv_mktemp(SCR *, char *, const char *, int);
 
+#ifndef O_REGULAR
+#define O_REGULAR O_NONBLOCK
+#endif
+
 /*
  * rcv_tmp --
  *     Build a file name that will be used as the recovery file.
@@ -286,7 +291,7 @@
 
                /* REQUEST: send email. */
                if (LF_ISSET(RCV_EMAIL))
-                       rcv_email(sp, ep->rcv_mpath);
+                       rcv_email(sp, ep->rcv_fd);
        }
 
        /*
@@ -466,7 +471,7 @@
        }
 
        if (issync) {
-               rcv_email(sp, mpath);
+               rcv_email(sp, fd);
                if (close(fd)) {
 werr:                  msgq(sp, M_SYSERR, "065|Recovery file");
                        goto err;
@@ -487,14 +492,19 @@
  * This is simpler than checking for getuid() == st.st_uid and we want
  * to preserve the functionality that root can recover anything which
  * means that root should know better and be careful.
+ *
+ * Checking the mode is racy though (someone can chmod between the
+ * open and the stat call, so also check for uid match or root.
  */
 static int
 checkok(int fd)
 {
        struct stat sb;
+       uid_t uid = getuid();
 
        return fstat(fd, &sb) != -1 && S_ISREG(sb.st_mode) &&
-           (sb.st_mode & (S_IRWXG|S_IRWXO)) == 0;
+           (sb.st_mode & (S_IRWXG|S_IRWXO)) == 0 &&
+           (uid == 0 || uid == sb.st_uid);
 }
 
 /*
@@ -659,7 +669,7 @@
                 * if we're using fcntl(2), there's no way to lock a file
                 * descriptor that's not open for writing.
                 */
-               if ((fd = open(recpath, O_RDWR|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC,
+               if ((fd = open(recpath, O_RDWR|O_REGULAR|O_NOFOLLOW|O_CLOEXEC,
                    0)) == -1)
                        continue;
 
@@ -876,12 +886,10 @@
  *     Send email.
  */
 static void
-rcv_email(SCR *sp, const char *fname)
+rcv_email(SCR *sp, int fd)
 {
        struct stat sb;
-       char buf[BUFSIZ];
-       FILE *fin, *fout;
-       size_t l;
+       pid_t pid;
 
        if (_PATH_SENDMAIL[0] != '/' || stat(_PATH_SENDMAIL, &sb) == -1) {
                msgq_str(sp, M_SYSERR,
@@ -896,28 +904,26 @@
         * for the recipients instead of specifying them some other
         * way.
         */
-       if ((fin = fopen(fname, "refl")) == NULL) {
-               msgq_str(sp, M_SYSERR,
-                   fname, "325|cannot open: %s");
-               return;
-       }
-
-       if (!checkok(fileno(fin))) {
-               (void)fclose(fin);
-               return;
+       switch (pid = fork()) {
+       case -1:                /* Error. */
+               msgq(sp, M_SYSERR, "fork");
+               break;
+       case 0:                 /* Sendmail. */
+               if (lseek(fd, 0, SEEK_SET) == -1) {
+                       msgq(sp, M_SYSERR, "lseek");
+                       _exit(127);
+               }
+               if (fd != STDIN_FILENO) {
+                       (void)dup2(fd, STDIN_FILENO);
+                       (void)close(fd);
+               }
+               execl(_PATH_SENDMAIL, "sendmail", "-t", NULL);
+               msgq(sp, M_SYSERR, _PATH_SENDMAIL);
+               _exit(127);
+       default:                /* Parent. */
+               while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
+                       continue;
+               break;
        }
 
-       fout = popen(_PATH_SENDMAIL " -t", "w");
-       if (fout == NULL) {
-               msgq_str(sp, M_SYSERR,
-                   _PATH_SENDMAIL, "326|cannot execute sendmail: %s");
-               fclose(fin);
-               return;
-       }
-
-       while ((l = fread(buf, 1, sizeof(buf), fin)) != 0)
-               (void)fwrite(buf, 1, l, fout);
-
-       (void)fclose(fin);
-       (void)pclose(fout);
 }
diff -r bbcdb3933cc5 -r 5dc249a5ef65 lib/libc/stdio/fdopen.c
--- a/lib/libc/stdio/fdopen.c   Thu Apr 12 01:38:42 2018 +0000
+++ b/lib/libc/stdio/fdopen.c   Thu Apr 12 01:45:57 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fdopen.c,v 1.17 2017/01/10 17:00:58 christos Exp $     */
+/*     $NetBSD: fdopen.c,v 1.17.6.1 2018/04/12 01:45:57 msaitoh Exp $  */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)fdopen.c   8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: fdopen.c,v 1.17 2017/01/10 17:00:58 christos Exp $");
+__RCSID("$NetBSD: fdopen.c,v 1.17.6.1 2018/04/12 01:45:57 msaitoh Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -92,7 +92,7 @@
                return NULL;
        }
 
-       if (oflags & O_NONBLOCK) {
+       if (oflags & O_REGULAR) {
                struct stat st;
                if (fstat(fd, &st) == -1) {
                        return NULL;
diff -r bbcdb3933cc5 -r 5dc249a5ef65 lib/libc/stdio/flags.c
--- a/lib/libc/stdio/flags.c    Thu Apr 12 01:38:42 2018 +0000
+++ b/lib/libc/stdio/flags.c    Thu Apr 12 01:45:57 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: flags.c,v 1.17 2012/11/15 03:50:36 christos Exp $      */
+/*     $NetBSD: flags.c,v 1.17.22.1 2018/04/12 01:45:57 msaitoh Exp $  */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)flags.c    8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: flags.c,v 1.17 2012/11/15 03:50:36 christos Exp $");
+__RCSID("$NetBSD: flags.c,v 1.17.22.1 2018/04/12 01:45:57 msaitoh Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -99,7 +99,7 @@
                        m = O_RDWR;
                        break;
                case 'f':
-                       o |= O_NONBLOCK;
+                       o |= O_REGULAR;
                        break;
                case 'e':
                        o |= O_CLOEXEC;
diff -r bbcdb3933cc5 -r 5dc249a5ef65 lib/libc/stdio/fopen.c
--- a/lib/libc/stdio/fopen.c    Thu Apr 12 01:38:42 2018 +0000
+++ b/lib/libc/stdio/fopen.c    Thu Apr 12 01:45:57 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fopen.c,v 1.15 2012/03/15 18:22:30 christos Exp $      */
+/*     $NetBSD: fopen.c,v 1.15.24.1 2018/04/12 01:45:57 msaitoh Exp $  */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)fopen.c    8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: fopen.c,v 1.15 2012/03/15 18:22:30 christos Exp $");
+__RCSID("$NetBSD: fopen.c,v 1.15.24.1 2018/04/12 01:45:57 msaitoh Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -66,20 +66,6 @@
                return NULL;
        if ((f = open(file, oflags, DEFFILEMODE)) < 0)
                goto release;
-       if (oflags & O_NONBLOCK) {
-               struct stat st;
-               if (fstat(f, &st) == -1) {
-                       int sverrno = errno;
-                       (void)close(f);
-                       errno = sverrno;
-                       goto release;
-               }
-               if (!S_ISREG(st.st_mode)) {
-                       (void)close(f);
-                       errno = EFTYPE;
-                       goto release;
-               }
-       }
        /*
         * File descriptors are a full int, but _file is only a short.
         * If we get a valid file descriptor that is greater or equal to
diff -r bbcdb3933cc5 -r 5dc249a5ef65 lib/libc/stdio/freopen.c
--- a/lib/libc/stdio/freopen.c  Thu Apr 12 01:38:42 2018 +0000
+++ b/lib/libc/stdio/freopen.c  Thu Apr 12 01:45:57 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: freopen.c,v 1.19 2012/03/27 15:05:42 christos Exp $    */
+/*     $NetBSD: freopen.c,v 1.19.24.1 2018/04/12 01:45:57 msaitoh Exp $        */
 
 /*-
  * Copyright (c) 1990, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)freopen.c  8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: freopen.c,v 1.19 2012/03/27 15:05:42 christos Exp $");
+__RCSID("$NetBSD: freopen.c,v 1.19.24.1 2018/04/12 01:45:57 msaitoh Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -141,21 +141,6 @@
                return NULL;
        }
 
-       if (oflags & O_NONBLOCK) {
-               struct stat st;
-               if (fstat(f, &st) == -1) {
-                       sverrno = errno;
-                       (void)close(f);
-                       errno = sverrno;
-                       return NULL;
-               }
-               if (!S_ISREG(st.st_mode)) {
-                       (void)close(f);
-                       errno = EFTYPE;
-                       return NULL;
-               }
-       }
-
        /*
         * If reopening something that was open before on a real file, try
         * to maintain the descriptor.  Various C library routines (perror)
diff -r bbcdb3933cc5 -r 5dc249a5ef65 lib/libc/sys/open.2
--- a/lib/libc/sys/open.2       Thu Apr 12 01:38:42 2018 +0000
+++ b/lib/libc/sys/open.2       Thu Apr 12 01:45:57 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: open.2,v 1.57 2017/05/14 12:30:37 wiz Exp $
+.\"    $NetBSD: open.2,v 1.57.2.1 2018/04/12 01:45:57 msaitoh Exp $
 .\"
 .\" Copyright (c) 1980, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)open.2     8.2 (Berkeley) 11/16/93
 .\"
-.Dd July 29, 2013



Home | Main Index | Thread Index | Old Index