Module Name: src Committed By: msaitoh Date: Thu Apr 12 01:45:58 UTC 2018
Modified Files: src/external/bsd/nvi/dist/common [netbsd-8]: recover.c src/lib/libc/stdio [netbsd-8]: fdopen.c flags.c fopen.c freopen.c src/lib/libc/sys [netbsd-8]: open.2 src/sys/kern [netbsd-8]: vfs_vnops.c src/sys/sys [netbsd-8]: fcntl.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.5.22.1 -r1.5.22.2 src/external/bsd/nvi/dist/common/recover.c cvs rdiff -u -r1.17 -r1.17.6.1 src/lib/libc/stdio/fdopen.c cvs rdiff -u -r1.17 -r1.17.22.1 src/lib/libc/stdio/flags.c cvs rdiff -u -r1.15 -r1.15.24.1 src/lib/libc/stdio/fopen.c cvs rdiff -u -r1.19 -r1.19.24.1 src/lib/libc/stdio/freopen.c cvs rdiff -u -r1.57 -r1.57.2.1 src/lib/libc/sys/open.2 cvs rdiff -u -r1.195 -r1.195.6.1 src/sys/kern/vfs_vnops.c cvs rdiff -u -r1.48.8.1 -r1.48.8.2 src/sys/sys/fcntl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/nvi/dist/common/recover.c diff -u src/external/bsd/nvi/dist/common/recover.c:1.5.22.1 src/external/bsd/nvi/dist/common/recover.c:1.5.22.2 --- src/external/bsd/nvi/dist/common/recover.c:1.5.22.1 Mon Nov 6 09:37:24 2017 +++ src/external/bsd/nvi/dist/common/recover.c Thu Apr 12 01:45:57 2018 @@ -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 @@ __RCSID("$NetBSD: recover.c,v 1.5.22.1 2 #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 @@ rcv_sync(SCR *sp, u_int flags) /* REQUEST: send email. */ if (LF_ISSET(RCV_EMAIL)) - rcv_email(sp, ep->rcv_mpath); + rcv_email(sp, ep->rcv_fd); } /* @@ -466,7 +471,7 @@ wout: *t2++ = '\n'; } 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 @@ err: if (!issync) * 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 @@ rcv_read(SCR *sp, FREF *frp) * 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 @@ rcv_mktemp(SCR *sp, char *path, const ch * 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 @@ rcv_email(SCR *sp, const char *fname) * 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; - } - - fout = popen(_PATH_SENDMAIL " -t", "w"); - if (fout == NULL) { - msgq_str(sp, M_SYSERR, - _PATH_SENDMAIL, "326|cannot execute sendmail: %s"); - 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; } - while ((l = fread(buf, 1, sizeof(buf), fin)) != 0) - (void)fwrite(buf, 1, l, fout); - - (void)fclose(fin); - (void)pclose(fout); } Index: src/lib/libc/stdio/fdopen.c diff -u src/lib/libc/stdio/fdopen.c:1.17 src/lib/libc/stdio/fdopen.c:1.17.6.1 --- src/lib/libc/stdio/fdopen.c:1.17 Tue Jan 10 17:00:58 2017 +++ src/lib/libc/stdio/fdopen.c Thu Apr 12 01:45:57 2018 @@ -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 @@ fdopen(int fd, const char *mode) return NULL; } - if (oflags & O_NONBLOCK) { + if (oflags & O_REGULAR) { struct stat st; if (fstat(fd, &st) == -1) { return NULL; Index: src/lib/libc/stdio/flags.c diff -u src/lib/libc/stdio/flags.c:1.17 src/lib/libc/stdio/flags.c:1.17.22.1 --- src/lib/libc/stdio/flags.c:1.17 Thu Nov 15 03:50:36 2012 +++ src/lib/libc/stdio/flags.c Thu Apr 12 01:45:57 2018 @@ -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 @@ __sflags(const char *mode, int *optr) m = O_RDWR; break; case 'f': - o |= O_NONBLOCK; + o |= O_REGULAR; break; case 'e': o |= O_CLOEXEC; Index: src/lib/libc/stdio/fopen.c diff -u src/lib/libc/stdio/fopen.c:1.15 src/lib/libc/stdio/fopen.c:1.15.24.1 --- src/lib/libc/stdio/fopen.c:1.15 Thu Mar 15 18:22:30 2012 +++ src/lib/libc/stdio/fopen.c Thu Apr 12 01:45:57 2018 @@ -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 @@ fopen(const char *file, const char *mode 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 Index: src/lib/libc/stdio/freopen.c diff -u src/lib/libc/stdio/freopen.c:1.19 src/lib/libc/stdio/freopen.c:1.19.24.1 --- src/lib/libc/stdio/freopen.c:1.19 Tue Mar 27 15:05:42 2012 +++ src/lib/libc/stdio/freopen.c Thu Apr 12 01:45:57 2018 @@ -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 @@ freopen(const char *file, const char *mo 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) Index: src/lib/libc/sys/open.2 diff -u src/lib/libc/sys/open.2:1.57 src/lib/libc/sys/open.2:1.57.2.1 --- src/lib/libc/sys/open.2:1.57 Sun May 14 12:30:37 2017 +++ src/lib/libc/sys/open.2 Thu Apr 12 01:45:57 2018 @@ -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 +.Dd November 9, 2017 .Dt OPEN 2 .Os .Sh NAME @@ -188,6 +188,8 @@ using an interface that supports scatter element of the request must meet the above alignment constraints. .It Dv O_DIRECTORY Fail if the file is not a directory. +.It Dv O_REGULAR +Fail if the path does not refer to a regular file. .It Dv O_ASYNC Enable the .Dv SIGIO Index: src/sys/kern/vfs_vnops.c diff -u src/sys/kern/vfs_vnops.c:1.195 src/sys/kern/vfs_vnops.c:1.195.6.1 --- src/sys/kern/vfs_vnops.c:1.195 Thu Mar 30 09:13:37 2017 +++ src/sys/kern/vfs_vnops.c Thu Apr 12 01:45:57 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnops.c,v 1.195 2017/03/30 09:13:37 hannken Exp $ */ +/* $NetBSD: vfs_vnops.c,v 1.195.6.1 2018/04/12 01:45:57 msaitoh Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.195 2017/03/30 09:13:37 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.195.6.1 2018/04/12 01:45:57 msaitoh Exp $"); #include "veriexec.h" @@ -299,6 +299,9 @@ vn_openchk(struct vnode *vp, kauth_cred_ if ((fflags & O_DIRECTORY) != 0 && vp->v_type != VDIR) return ENOTDIR; + if ((fflags & O_REGULAR) != 0 && vp->v_type != VREG) + return EFTYPE; + if ((fflags & FREAD) != 0) { permbits = VREAD; } Index: src/sys/sys/fcntl.h diff -u src/sys/sys/fcntl.h:1.48.8.1 src/sys/sys/fcntl.h:1.48.8.2 --- src/sys/sys/fcntl.h:1.48.8.1 Sun Feb 25 23:57:51 2018 +++ src/sys/sys/fcntl.h Thu Apr 12 01:45:57 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: fcntl.h,v 1.48.8.1 2018/02/25 23:57:51 snj Exp $ */ +/* $NetBSD: fcntl.h,v 1.48.8.2 2018/04/12 01:45:57 msaitoh Exp $ */ /*- * Copyright (c) 1983, 1990, 1993 @@ -120,6 +120,7 @@ #endif #if defined(_NETBSD_SOURCE) #define O_NOSIGPIPE 0x01000000 /* don't deliver sigpipe */ +#define O_REGULAR 0x02000000 /* fail if not a regular file */ #endif #ifdef _KERNEL @@ -131,7 +132,7 @@ #define O_MASK (O_ACCMODE|O_NONBLOCK|O_APPEND|O_SHLOCK|O_EXLOCK|\ O_ASYNC|O_SYNC|O_CREAT|O_TRUNC|O_EXCL|O_DSYNC|\ O_RSYNC|O_NOCTTY|O_ALT_IO|O_NOFOLLOW|O_DIRECT|\ - O_DIRECTORY|O_CLOEXEC|O_NOSIGPIPE) + O_DIRECTORY|O_CLOEXEC|O_NOSIGPIPE|O_REGULAR) #define FMARK 0x00001000 /* mark during gc() */ #define FDEFER 0x00002000 /* defer for next gc pass */