Module Name:    src
Committed By:   snj
Date:           Tue Aug  4 21:03:33 UTC 2015

Modified Files:
        src/usr.bin/patch [netbsd-7]: common.h inp.c patch.1

Log Message:
Pull up following revision(s) (requested by christos in ticket #918):
        usr.bin/patch/patch.1: revisions 1.18, 1.19
        usr.bin/patch/common.h: revision 1.21
        usr.bin/patch/inp.c: revision 1.24
>From Martin Natano @bitrig: Use execve(2) instead of system to apply patches
that require rcs command execution instead system(3) to avoid malicious
filenames in patches causing bad things to happen. In the process, lose SCCS
support. It is not like we are shipping sccs commands for that to work.
--
Use absolute paths for RCS commands (Martin Natano)
--
remove reference to SCCS which is not supported anymore.
--
Fix two typos.


To generate a diff of this commit:
cvs rdiff -u -r1.19.38.1 -r1.19.38.2 src/usr.bin/patch/common.h
cvs rdiff -u -r1.23 -r1.23.24.1 src/usr.bin/patch/inp.c
cvs rdiff -u -r1.17 -r1.17.2.1 src/usr.bin/patch/patch.1

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/patch/common.h
diff -u src/usr.bin/patch/common.h:1.19.38.1 src/usr.bin/patch/common.h:1.19.38.2
--- src/usr.bin/patch/common.h:1.19.38.1	Fri Nov 28 09:09:19 2014
+++ src/usr.bin/patch/common.h	Tue Aug  4 21:03:33 2015
@@ -1,7 +1,7 @@
 /*
  * $OpenBSD: common.h,v 1.26 2006/03/11 19:41:30 otto Exp $
  * $DragonFly: src/usr.bin/patch/common.h,v 1.5 2008/08/10 23:50:12 joerg Exp $
- * $NetBSD: common.h,v 1.19.38.1 2014/11/28 09:09:19 martin Exp $
+ * $NetBSD: common.h,v 1.19.38.2 2015/08/04 21:03:33 snj Exp $
  */
 
 /*
@@ -50,8 +50,8 @@
 #define SCCSDIFF "get -p %s | diff - %s >/dev/null"
 
 #define RCSSUFFIX ",v"
-#define CHECKOUT "co -l %s"
-#define RCSDIFF "rcsdiff %s > /dev/null"
+#define CHECKOUT "/usr/bin/co"
+#define RCSDIFF "/usr/bin/rcsdiff"
 
 #define ORIGEXT ".orig"
 #define REJEXT ".rej"

Index: src/usr.bin/patch/inp.c
diff -u src/usr.bin/patch/inp.c:1.23 src/usr.bin/patch/inp.c:1.23.24.1
--- src/usr.bin/patch/inp.c:1.23	Wed Oct 21 17:16:11 2009
+++ src/usr.bin/patch/inp.c	Tue Aug  4 21:03:33 2015
@@ -1,7 +1,7 @@
 /*
  * $OpenBSD: inp.c,v 1.34 2006/03/11 19:41:30 otto Exp $
  * $DragonFly: src/usr.bin/patch/inp.c,v 1.6 2007/09/29 23:11:10 swildner Exp $
- * $NetBSD: inp.c,v 1.23 2009/10/21 17:16:11 joerg Exp $
+ * $NetBSD: inp.c,v 1.23.24.1 2015/08/04 21:03:33 snj Exp $
  */
 
 /*
@@ -31,14 +31,16 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: inp.c,v 1.23 2009/10/21 17:16:11 joerg Exp $");
+__RCSID("$NetBSD: inp.c,v 1.23.24.1 2015/08/04 21:03:33 snj Exp $");
 
 #include <sys/types.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
 
 #include <ctype.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
 #include <limits.h>
@@ -139,12 +141,14 @@ reallocate_lines(size_t *lines_allocated
 static bool
 plan_a(const char *filename)
 {
-	int		ifd, statfailed;
+	int		ifd, statfailed, devnull, pstat;
 	char		*p, *s, lbuf[MAXLINELEN];
 	struct stat	filestat;
 	off_t		i;
 	ptrdiff_t	sz;
 	size_t		iline, lines_allocated;
+	pid_t		pid;
+	char		*argp[4] = {NULL};
 
 #ifdef DEBUGGING
 	if (debug & 8)
@@ -172,13 +176,13 @@ plan_a(const char *filename)
 	}
 	if (statfailed && check_only)
 		fatal("%s not found, -C mode, can't probe further\n", filename);
-	/* For nonexistent or read-only files, look for RCS or SCCS versions.  */
+	/* For nonexistent or read-only files, look for RCS versions.  */
 	if (statfailed ||
 	    /* No one can write to it.  */
 	    (filestat.st_mode & 0222) == 0 ||
 	    /* I can't write to it.  */
 	    ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
-		const char	*cs = NULL, *filebase, *filedir;
+		char	*filebase, *filedir;
 		struct stat	cstat;
 		char *tmp_filename1, *tmp_filename2;
 
@@ -186,43 +190,26 @@ plan_a(const char *filename)
 		tmp_filename2 = strdup(filename);
 		if (tmp_filename1 == NULL || tmp_filename2 == NULL)
 			fatal("strdupping filename");
-		filebase = basename(tmp_filename1);
-		filedir = dirname(tmp_filename2);
-
-		/* Leave room in lbuf for the diff command.  */
-		s = lbuf + 20;
-
+ 
+ 		filebase = basename(tmp_filename1);
+ 		filedir = dirname(tmp_filename2);
+ 
 #define try(f, a1, a2, a3) \
-	(snprintf(s, sizeof lbuf - 20, f, a1, a2, a3), stat(s, &cstat) == 0)
-
-		if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
-		    try("%s/RCS/%s%s", filedir, filebase, "") ||
-		    try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
-			snprintf(buf, buf_len, CHECKOUT, filename);
-			snprintf(lbuf, sizeof lbuf, RCSDIFF, filename);
-			cs = "RCS";
-		} else if (try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
-		    try("%s/%s%s", filedir, SCCSPREFIX, filebase)) {
-			snprintf(buf, buf_len, GET, s);
-			snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename);
-			cs = "SCCS";
-		} else if (statfailed)
-			fatal("can't find %s\n", filename);
-
-		free(tmp_filename1);
-		free(tmp_filename2);
+	(snprintf(lbuf, sizeof lbuf, f, a1, a2, a3), stat(lbuf, &cstat) == 0)
 
 		/*
 		 * else we can't write to it but it's not under a version
 		 * control system, so just proceed.
 		 */
-		if (cs) {
+		if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
+		    try("%s/RCS/%s%s", filedir, filebase, "") ||
+		    try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
 			if (!statfailed) {
 				if ((filestat.st_mode & 0222) != 0)
 					/* The owner can write to it.  */
 					fatal("file %s seems to be locked "
-					    "by somebody else under %s\n",
-					    filename, cs);
+					    "by somebody else under RCS\n",
+					    filename);
 				/*
 				 * It might be checked out unlocked.  See if
 				 * it's safe to check out the default version
@@ -230,21 +217,59 @@ plan_a(const char *filename)
 				 */
 				if (verbose)
 					say("Comparing file %s to default "
-					    "%s version...\n",
-					    filename, cs);
-				if (system(lbuf))
+					    "RCS version...\n", filename);
+
+				switch (pid = fork()) {
+				case -1:
+					fatal("can't fork: %s\n",
+					    strerror(errno));
+				case 0:
+					devnull = open("/dev/null", O_RDONLY);
+					if (devnull == -1) {
+						fatal("can't open /dev/null: %s",
+						    strerror(errno));
+					}
+					(void)dup2(devnull, STDOUT_FILENO);
+					argp[0] = __UNCONST(RCSDIFF);
+					argp[1] = __UNCONST(filename);
+					execv(RCSDIFF, argp);
+					exit(127);
+				}
+				pid = waitpid(pid, &pstat, 0);
+				if (pid == -1 || WEXITSTATUS(pstat) != 0) {
 					fatal("can't check out file %s: "
-					    "differs from default %s version\n",
-					    filename, cs);
+					    "differs from default RCS version\n",
+					    filename);
+				}
 			}
+
 			if (verbose)
-				say("Checking out file %s from %s...\n",
-				    filename, cs);
-			if (system(buf) || stat(filename, &filestat))
-				fatal("can't check out file %s from %s\n",
-				    filename, cs);
+				say("Checking out file %s from RCS...\n",
+				    filename);
+
+			switch (pid = fork()) {
+			case -1:
+				fatal("can't fork: %s\n", strerror(errno));
+			case 0:
+				argp[0] = __UNCONST(CHECKOUT);
+				argp[1] = __UNCONST("-l");
+				argp[2] = __UNCONST(filename);
+				execv(CHECKOUT, argp);
+				exit(127);
+			}
+			pid = waitpid(pid, &pstat, 0);
+			if (pid == -1 || WEXITSTATUS(pstat) != 0 ||
+			    stat(filename, &filestat)) {
+				fatal("can't check out file %s from RCS\n",
+				    filename);
+			}
+		} else if (statfailed) {
+			fatal("can't find %s\n", filename);
 		}
+		free(tmp_filename1);
+		free(tmp_filename2);
 	}
+
 	filemode = filestat.st_mode;
 	if (!S_ISREG(filemode))
 		fatal("%s is not a normal file--can't patch\n", filename);

Index: src/usr.bin/patch/patch.1
diff -u src/usr.bin/patch/patch.1:1.17 src/usr.bin/patch/patch.1:1.17.2.1
--- src/usr.bin/patch/patch.1:1.17	Fri Apr 11 17:41:09 2014
+++ src/usr.bin/patch/patch.1	Tue Aug  4 21:03:33 2015
@@ -1,6 +1,6 @@
 .\"	$OpenBSD: patch.1,v 1.22 2008/06/06 20:44:00 jmc Exp $
 .\"	$DragonFly: src/usr.bin/patch/patch.1,v 1.10 2008/08/18 19:15:55 joerg Exp $
-.\"	$NetBSD: patch.1,v 1.17 2014/04/11 17:41:09 christos Exp $
+.\"	$NetBSD: patch.1,v 1.17.2.1 2015/08/04 21:03:33 snj Exp $
 .\" Copyright 1986, Larry Wall
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -21,7 +21,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 11, 2014
+.Dd August 2, 2015
 .Dt PATCH 1
 .Os
 .Sh NAME
@@ -445,9 +445,8 @@ the shortest basename, and the shortest 
 .It
 If no file exists,
 .Nm
-checks for the existence of the files in an SCCS or RCS directory
-(using the appropriate prefix or suffix) using the criteria specified
-above.
+checks for the existence of the files in an RCS directory using the criteria
+specified above.
 If found,
 .Nm
 will attempt to get or check out the file.

Reply via email to