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 */