Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

devel/patch: security fixes #33

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions devel/patch/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# $NetBSD: Makefile,v 1.44 2018/03/03 01:31:35 mef Exp $

DISTNAME= patch-2.7.6
PKGREVISION= 1
CATEGORIES= devel
MASTER_SITES= ${MASTER_SITE_GNU:=patch/}
EXTRACT_SUFX= .tar.xz
Expand All @@ -20,13 +21,6 @@ CONFIGURE_ENV+= ac_cv_func_setmode_dos=no # Fix for Interix (and old bsd?)

INSTALLATION_DIRS= ${PKGGNUDIR}bin ${PKGGNUDIR}${PKGMANDIR}/man1

do-patch:
.for stdhdr in sys/param.h sys/stat.h string.h
${ECHO} "#ifdef HAVE_${stdhdr:tu:C,[/.],_,g}" >> ${WRKSRC}/config.hin
${ECHO} "#include <${stdhdr}>" >> ${WRKSRC}/config.hin
${ECHO} "#endif" >> ${WRKSRC}/config.hin
.endfor

SYMLINKS = bin/gpatch ${PKGGNUDIR}bin/patch \
man/man1/gpatch.1 ${PKGGNUDIR}${PKGMANDIR}/man1/patch.1
post-install:
Expand Down
3 changes: 3 additions & 0 deletions devel/patch/distinfo
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ SHA1 (patch-2.7.6.tar.xz) = 6f64fa75993bdb285ac4ed6eca6c9212725bff91
RMD160 (patch-2.7.6.tar.xz) = 439753620b4d27d606110093d0e586719b8451c3
SHA512 (patch-2.7.6.tar.xz) = fcca87bdb67a88685a8a25597f9e015f5e60197b9a269fa350ae35a7991ed8da553939b4bbc7f7d3cfd863c67142af403b04165633acbce4339056a905e87fbd
Size (patch-2.7.6.tar.xz) = 783756 bytes
SHA1 (patch-src_pch.c) = 0aed6cd0d64c380767c39908c388c91ddf3003d1
SHA1 (patch-tests_Makefile.in) = 6ae000cd78d4946c8f76d5eb4322a9dd4e00ff55
SHA1 (patch-tests_ed-style) = 7d7c2d04eddaab1d07c05022908a98ef9c984e08
155 changes: 155 additions & 0 deletions devel/patch/patches/patch-src_pch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
$NetBSD$

- fixes: CVE-2018-6951 CVE-2018-6952 CVE-2018-1000156

- bugs: 53132 53133 53566
https://savannah.gnu.org/bugs/index.php?

- commit ids: f290f48a62 9c986353e4 123eaff0d5
https://git.savannah.gnu.org/cgit/patch.git/diff/?id=

--- src/pch.c.orig 2018-10-09 17:01:21.566749708 +0000
+++ src/pch.c
@@ -33,6 +33,7 @@
# include <io.h>
#endif
#include <safe.h>
+#include <sys/wait.h>

#define INITHUNKMAX 125 /* initial dynamic allocation size */

@@ -974,7 +975,8 @@ intuit_diff_type (bool need_header, mode
if ((pch_rename () || pch_copy ())
&& ! inname
&& ! ((i == OLD || i == NEW) &&
- p_name[! reverse] &&
+ p_name[reverse] && p_name[! reverse] &&
+ name_is_valid (p_name[reverse]) &&
name_is_valid (p_name[! reverse])))
{
say ("Cannot %s file without two valid file names\n", pch_rename () ? "rename" : "copy");
@@ -2113,7 +2115,7 @@ pch_swap (void)
}
if (p_efake >= 0) { /* fix non-freeable ptr range */
if (p_efake <= i)
- n = p_end - i + 1;
+ n = p_end - p_ptrn_lines;
else
n = -i;
p_efake += n;
@@ -2388,22 +2390,27 @@ do_ed_script (char const *inname, char c
static char const editor_program[] = EDITOR_PROGRAM;

file_offset beginning_of_this_line;
- FILE *pipefp = 0;
size_t chars_read;
+ FILE *tmpfp = 0;
+ char const *tmpname;
+ int tmpfd;
+ pid_t pid;

- if (! dry_run && ! skip_rest_of_patch) {
- int exclusive = *outname_needs_removal ? 0 : O_EXCL;
- assert (! inerrno);
- *outname_needs_removal = true;
- copy_file (inname, outname, 0, exclusive, instat.st_mode, true);
- sprintf (buf, "%s %s%s", editor_program,
- verbosity == VERBOSE ? "" : "- ",
- outname);
- fflush (stdout);
- pipefp = popen(buf, binary_transput ? "wb" : "w");
- if (!pipefp)
- pfatal ("Can't open pipe to %s", quotearg (buf));
- }
+ if (! dry_run && ! skip_rest_of_patch)
+ {
+ /* Write ed script to a temporary file. This causes ed to abort on
+ invalid commands such as when line numbers or ranges exceed the
+ number of available lines. When ed reads from a pipe, it rejects
+ invalid commands and treats the next line as a new command, which
+ can lead to arbitrary command execution. */
+
+ tmpfd = make_tempfile (&tmpname, 'e', NULL, O_RDWR | O_BINARY, 0);
+ if (tmpfd == -1)
+ pfatal ("Can't create temporary file %s", quotearg (tmpname));
+ tmpfp = fdopen (tmpfd, "w+b");
+ if (! tmpfp)
+ pfatal ("Can't open stream for file %s", quotearg (tmpname));
+ }
for (;;) {
char ed_command_letter;
beginning_of_this_line = file_tell (pfp);
@@ -2414,14 +2421,14 @@ do_ed_script (char const *inname, char c
}
ed_command_letter = get_ed_command_letter (buf);
if (ed_command_letter) {
- if (pipefp)
- if (! fwrite (buf, sizeof *buf, chars_read, pipefp))
+ if (tmpfp)
+ if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
write_fatal ();
if (ed_command_letter != 'd' && ed_command_letter != 's') {
p_pass_comments_through = true;
while ((chars_read = get_line ()) != 0) {
- if (pipefp)
- if (! fwrite (buf, sizeof *buf, chars_read, pipefp))
+ if (tmpfp)
+ if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
write_fatal ();
if (chars_read == 2 && strEQ (buf, ".\n"))
break;
@@ -2434,13 +2441,49 @@ do_ed_script (char const *inname, char c
break;
}
}
- if (!pipefp)
+ if (!tmpfp)
return;
- if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, pipefp) == 0
- || fflush (pipefp) != 0)
+ if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, tmpfp) == 0
+ || fflush (tmpfp) != 0)
write_fatal ();
- if (pclose (pipefp) != 0)
- fatal ("%s FAILED", editor_program);
+
+ if (lseek (tmpfd, 0, SEEK_SET) == -1)
+ pfatal ("Can't rewind to the beginning of file %s", quotearg (tmpname));
+
+ if (! dry_run && ! skip_rest_of_patch) {
+ int exclusive = *outname_needs_removal ? 0 : O_EXCL;
+ *outname_needs_removal = true;
+ if (inerrno != ENOENT)
+ {
+ *outname_needs_removal = true;
+ copy_file (inname, outname, 0, exclusive, instat.st_mode, true);
+ }
+ sprintf (buf, "%s %s%s", editor_program,
+ verbosity == VERBOSE ? "" : "- ",
+ outname);
+ fflush (stdout);
+
+ pid = fork();
+ if (pid == -1)
+ pfatal ("Can't fork");
+ else if (pid == 0)
+ {
+ dup2 (tmpfd, 0);
+ execl ("/bin/sh", "sh", "-c", buf, (char *) 0);
+ _exit (2);
+ }
+ else
+ {
+ int wstatus;
+ if (waitpid (pid, &wstatus, 0) == -1
+ || ! WIFEXITED (wstatus)
+ || WEXITSTATUS (wstatus) != 0)
+ fatal ("%s FAILED", editor_program);
+ }
+ }
+
+ fclose (tmpfp);
+ safe_unlink (tmpname);

if (ofp)
{
12 changes: 12 additions & 0 deletions devel/patch/patches/patch-tests_Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
$NetBSD$

--- tests/Makefile.in.orig 2018-02-03 13:33:56.000000000 +0000
+++ tests/Makefile.in
@@ -1308,6 +1308,7 @@ TESTS = \
crlf-handling \
dash-o-append \
deep-directories \
+ ed-style \
empty-files \
false-match \
fifo \
48 changes: 48 additions & 0 deletions devel/patch/patches/patch-tests_ed-style
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
$NetBSD$

- Add ed-style test, related to CVE-2018-1000156 fix.

--- tests/ed-style.orig 2018-10-09 17:51:47.148455875 +0000
+++ tests/ed-style
@@ -0,0 +1,41 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# in any medium, are permitted without royalty provided the copyright
+# notice and this notice are preserved.
+
+. $srcdir/test-lib.sh
+
+require cat
+use_local_patch
+use_tmpdir
+
+# ==============================================================
+
+cat > ed1.diff <<EOF
+0a
+foo
+.
+EOF
+
+check 'patch -e foo -i ed1.diff' <<EOF
+EOF
+
+check 'cat foo' <<EOF
+foo
+EOF
+
+cat > ed2.diff <<EOF
+1337a
+r !echo bar
+,p
+EOF
+
+check 'patch -e foo -i ed2.diff 2> /dev/null || echo "Status: $?"' <<EOF
+?
+Status: 2
+EOF
+
+check 'cat foo' <<EOF
+foo
+EOF