diff --git a/SOURCES/patch-2.7.6-CVE-2019-13636-symlinks.patch b/SOURCES/patch-2.7.6-CVE-2019-13636-symlinks.patch new file mode 100644 index 0000000..bf3e603 --- /dev/null +++ b/SOURCES/patch-2.7.6-CVE-2019-13636-symlinks.patch @@ -0,0 +1,102 @@ +commit dce4683cbbe107a95f1f0d45fabc304acfb5d71a +Author: Andreas Gruenbacher +Date: Mon Jul 15 16:21:48 2019 +0200 + + Don't follow symlinks unless --follow-symlinks is given + + * src/inp.c (plan_a, plan_b), src/util.c (copy_to_fd, copy_file, + append_to_file): Unless the --follow-symlinks option is given, open files with + the O_NOFOLLOW flag to avoid following symlinks. So far, we were only doing + that consistently for input files. + * src/util.c (create_backup): When creating empty backup files, (re)create them + with O_CREAT | O_EXCL to avoid following symlinks in that case as well. + +diff --git a/src/inp.c b/src/inp.c +index 32d0919..22d7473 100644 +--- a/src/inp.c ++++ b/src/inp.c +@@ -238,8 +238,13 @@ plan_a (char const *filename) + { + if (S_ISREG (instat.st_mode)) + { +- int ifd = safe_open (filename, O_RDONLY|binary_transput, 0); ++ int flags = O_RDONLY | binary_transput; + size_t buffered = 0, n; ++ int ifd; ++ ++ if (! follow_symlinks) ++ flags |= O_NOFOLLOW; ++ ifd = safe_open (filename, flags, 0); + if (ifd < 0) + pfatal ("can't open file %s", quotearg (filename)); + +@@ -340,6 +345,7 @@ plan_a (char const *filename) + static void + plan_b (char const *filename) + { ++ int flags = O_RDONLY | binary_transput; + int ifd; + FILE *ifp; + int c; +@@ -353,7 +359,9 @@ plan_b (char const *filename) + + if (instat.st_size == 0) + filename = NULL_DEVICE; +- if ((ifd = safe_open (filename, O_RDONLY | binary_transput, 0)) < 0 ++ if (! follow_symlinks) ++ flags |= O_NOFOLLOW; ++ if ((ifd = safe_open (filename, flags, 0)) < 0 + || ! (ifp = fdopen (ifd, binary_transput ? "rb" : "r"))) + pfatal ("Can't open file %s", quotearg (filename)); + if (TMPINNAME_needs_removal) +diff --git a/src/util.c b/src/util.c +index 1cc08ba..fb38307 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -388,7 +388,7 @@ create_backup (char const *to, const struct stat *to_st, bool leave_original) + + try_makedirs_errno = ENOENT; + safe_unlink (bakname); +- while ((fd = safe_open (bakname, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) ++ while ((fd = safe_open (bakname, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, 0666)) < 0) + { + if (errno != try_makedirs_errno) + pfatal ("Can't create file %s", quotearg (bakname)); +@@ -579,10 +579,13 @@ create_file (char const *file, int open_flags, mode_t mode, + static void + copy_to_fd (const char *from, int tofd) + { ++ int from_flags = O_RDONLY | O_BINARY; + int fromfd; + ssize_t i; + +- if ((fromfd = safe_open (from, O_RDONLY | O_BINARY, 0)) < 0) ++ if (! follow_symlinks) ++ from_flags |= O_NOFOLLOW; ++ if ((fromfd = safe_open (from, from_flags, 0)) < 0) + pfatal ("Can't reopen file %s", quotearg (from)); + while ((i = read (fromfd, buf, bufsize)) != 0) + { +@@ -625,6 +628,8 @@ copy_file (char const *from, char const *to, struct stat *tost, + else + { + assert (S_ISREG (mode)); ++ if (! follow_symlinks) ++ to_flags |= O_NOFOLLOW; + tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode, + to_dir_known_to_exist); + copy_to_fd (from, tofd); +@@ -640,9 +645,12 @@ copy_file (char const *from, char const *to, struct stat *tost, + void + append_to_file (char const *from, char const *to) + { ++ int to_flags = O_WRONLY | O_APPEND | O_BINARY; + int tofd; + +- if ((tofd = safe_open (to, O_WRONLY | O_BINARY | O_APPEND, 0)) < 0) ++ if (! follow_symlinks) ++ to_flags |= O_NOFOLLOW; ++ if ((tofd = safe_open (to, to_flags, 0)) < 0) + pfatal ("Can't reopen file %s", quotearg (to)); + copy_to_fd (from, tofd); + if (close (tofd) != 0) diff --git a/SOURCES/patch-2.7.x-abort_when_cleaning_up_fails.patch b/SOURCES/patch-2.7.x-abort_when_cleaning_up_fails.patch new file mode 100644 index 0000000..56dbda8 --- /dev/null +++ b/SOURCES/patch-2.7.x-abort_when_cleaning_up_fails.patch @@ -0,0 +1,46 @@ +commit b7b028a77bd855f6f56b17c8837fc1cca77b469d +Author: Andreas Gruenbacher +Date: Fri Jun 28 00:30:25 2019 +0200 + + Abort when cleaning up fails + + When a fatal error triggers during cleanup, another attempt will be made to + clean up, which will likely lead to the same fatal error. So instead, bail out + when that happens. + src/patch.c (cleanup): Bail out when called recursively. + (main): There is no need to call output_files() before cleanup() as cleanup() + already does that. + +diff --git a/src/patch.c b/src/patch.c +index 4616a48..02fd982 100644 +--- a/src/patch.c ++++ b/src/patch.c +@@ -685,7 +685,6 @@ main (int argc, char **argv) + } + if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0)) + write_fatal (); +- output_files (NULL); + cleanup (); + delete_files (); + if (somefailed) +@@ -1991,7 +1990,6 @@ void + fatal_exit (int sig) + { + cleanup (); +- + if (sig) + exit_with_signal (sig); + +@@ -2011,6 +2009,12 @@ remove_if_needed (char const *name, bool *needs_removal) + static void + cleanup (void) + { ++ static bool already_cleaning_up; ++ ++ if (already_cleaning_up) ++ return; ++ already_cleaning_up = true; ++ + remove_if_needed (TMPINNAME, &TMPINNAME_needs_removal); + remove_if_needed (TMPOUTNAME, &TMPOUTNAME_needs_removal); + remove_if_needed (TMPPATNAME, &TMPPATNAME_needs_removal); diff --git a/SPECS/patch.spec b/SPECS/patch.spec index e383c64..f94f346 100644 --- a/SPECS/patch.spec +++ b/SPECS/patch.spec @@ -3,7 +3,7 @@ Summary: Utility for modifying/upgrading files Name: patch Version: 2.7.6 -Release: 9%{?dist} +Release: 11%{?dist} License: GPLv3+ URL: http://www.gnu.org/software/patch/patch.html Group: Development/Tools @@ -13,6 +13,8 @@ Patch2: patch-CVE-2018-1000156.patch Patch3: patch-2.7.6-gcc8.patch Patch4: patch-2.7.6-CVE-2018-6952.patch Patch5: patch-2.7.6-CVE-2018-20969.patch +Patch6: patch-2.7.6-CVE-2019-13636-symlinks.patch +Patch7: patch-2.7.x-abort_when_cleaning_up_fails.patch Patch100: patch-selinux.patch BuildRequires: libselinux-devel BuildRequires: libattr-devel @@ -49,6 +51,12 @@ applications. # CVE-2018-20969, do_ed_script in pch.c does not block strings beginning with a ! character %patch5 -p1 -b .CVE-2018-20969 +# CVE-2019-13636, Don't follow symlinks unless --follow-symlinks is given +%patch6 -p1 -b .CVE-2019-13636 + +# bz#1665928, Abort when cleaning up fails +%patch7 -p1 -b .abort_when_cleaning_up_fails + # SELinux support. %patch100 -p1 -b .selinux @@ -75,6 +83,13 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/*/* %changelog +* Tue Nov 19 2019 Than Ngo - 2.7.6-11 +- Related: #1733565, apply the patch correctly + +* Tue Nov 19 2019 Than Ngo - 2.7.6-10 +- CVE-2019-13636 , Don't follow symlinks unless --follow-symlinks is given +- Resolves: #1665928, patch has a huge error output and segfaults when the file to be patched does not exist + * Mon Sep 02 2019 Than Ngo - 2.7.6-9 - CVE-2018-20969, invoke ed directly instead of using the shell