diff --git a/abort-when-cleaning-up-fails.patch b/abort-when-cleaning-up-fails.patch new file mode 100644 index 0000000..6052dd9 --- /dev/null +++ b/abort-when-cleaning-up-fails.patch @@ -0,0 +1,48 @@ +From: Andreas Gruenbacher +Date: Fri, 28 Jun 2019 00:30:25 +0200 +Subject: Abort when cleaning up fails +Patch-mainline: Yes +Git-commit: b7b028a77bd855f6f56b17c8837fc1cca77b469d +References: boo#1111572 savannah#54845 + +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. +--- + src/patch.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/src/patch.c ++++ b/src/patch.c +@@ -681,7 +681,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) +@@ -1977,7 +1976,6 @@ void + fatal_exit (int sig) + { + cleanup (); +- + if (sig) + exit_with_signal (sig); + +@@ -1997,6 +1995,12 @@ remove_if_needed (char const *name, bool + 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/dont-follow-symlinks-unless-asked.patch b/dont-follow-symlinks-unless-asked.patch new file mode 100644 index 0000000..b05afcb --- /dev/null +++ b/dont-follow-symlinks-unless-asked.patch @@ -0,0 +1,103 @@ +From: Andreas Gruenbacher +Date: Mon, 15 Jul 2019 16:21:48 +0200 +Subject: Don't follow symlinks unless --follow-symlinks is given +Patch-mainline: Yes +Git-commit: dce4683cbbe107a95f1f0d45fabc304acfb5d71a +References: boo#1142041 CVE-2019-13636 + +* 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. +--- + src/inp.c | 12 ++++++++++-- + src/util.c | 14 +++++++++++--- + 2 files changed, 21 insertions(+), 5 deletions(-) + +--- 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) +--- a/src/util.c ++++ b/src/util.c +@@ -388,7 +388,7 @@ create_backup (char const *to, const str + + 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_ + 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 + 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 + 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/fix-swapping-fake-lines-in-pch_swap.patch b/fix-swapping-fake-lines-in-pch_swap.patch new file mode 100644 index 0000000..0e90999 --- /dev/null +++ b/fix-swapping-fake-lines-in-pch_swap.patch @@ -0,0 +1,27 @@ +From: Andreas Gruenbacher +Date: Fri, 17 Aug 2018 13:35:40 +0200 +Subject: Fix swapping fake lines in pch_swap +Patch-mainline: Yes +Git-commit: 9c986353e420ead6e706262bf204d6e03322c300 +References: boo#1080985 savannah#53133 CVE-2018-6952 + +* src/pch.c (pch_swap): Fix swapping p_bfake and p_efake when there is a +blank line in the middle of a context-diff hunk: that empty line stays +in the middle of the hunk and isn't swapped. + +Fixes: https://savannah.gnu.org/bugs/index.php?53133 +--- + src/pch.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/pch.c ++++ b/src/pch.c +@@ -2115,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; diff --git a/pass-the-correct-stat-to-backup-files.patch b/pass-the-correct-stat-to-backup-files.patch new file mode 100644 index 0000000..a391393 --- /dev/null +++ b/pass-the-correct-stat-to-backup-files.patch @@ -0,0 +1,59 @@ +From: Takashi Iwai +Date: Wed, 6 Apr 2022 10:48:35 +0200 +Subject: Pass the correct stat to backup files +Patch-mainline: Yes +Git-commit: c835ecc67b7e37c0d0b7dd7e032209fdaa285808 +References: boo#1198106 savananh#62364 + +The last case to call output_file() in the main loop is + output_file (outname, NULL, &tmpoutst, NULL, NULL, + file_type | 0, backup); +and this essentially means to create a backup file (where to=NULL) +only if backup=true, and does nothing else. + +And, in the current code, the passed file stat (&tmpoutst) is a file +stat of the temporary file that has been processed, not the original +file (outname) to be backed up. When the backup is performed +immediately, this is no big problem. However, output_file() may +schedule the deferred handling, and the given file may be backed up at +a later point. The problem is that create_backup() tries to avoid the +backup of the same file twice, and it checks the given stat i-node +number in the hash list. Since it's a stat of a temporary file, the +same i-node number may be reused once a temp file is deleted and +another is created. This results in a false-positive detection of the +already existing file, eventually missing a backup file. + +This patch attempts to address the issue: +- Modify the condition for better understanding, clearly indicating + that the code there is for creating a backup file +- Pass the stat of the original file instead of a temporary file + +BugLink: https://bugzilla.opensuse.org/show_bug.cgi?id=1198106 +Signed-off-by: Takashi Iwai +Signed-off-by: Jean Delvare +--- + src/patch.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/src/patch.c ++++ b/src/patch.c +@@ -611,9 +611,16 @@ main (int argc, char **argv) + output_file (NULL, NULL, NULL, inname, &instat, + mode, backup); + } +- else +- output_file (outname, NULL, &tmpoutst, NULL, NULL, +- file_type | 0, backup); ++ else if (backup) ++ { ++ struct stat outstat; ++ ++ if (stat_file (outname, &outstat) != 0) ++ say ("Cannot stat file %s, skipping backup\n", outname); ++ else ++ output_file (outname, NULL, &outstat, NULL, NULL, ++ file_type | 0, true); ++ } + } + } + } diff --git a/patch.changes b/patch.changes index 763b7aa..d890878 100644 --- a/patch.changes +++ b/patch.changes @@ -1,3 +1,19 @@ +------------------------------------------------------------------- +Tue May 10 16:41:54 UTC 2022 - Jean Delvare + +- fix-swapping-fake-lines-in-pch_swap.patch: Fix swapping fake + lines in pch_swap. This bug was causing a double free leading to + a crash (boo#1080985 CVE-2018-6952). +- abort-when-cleaning-up-fails.patch: Abort when cleaning up fails. + This bug could cause an infinite loop when a patch wouldn't + apply, leading to a segmentation fault (boo#1111572). +- dont-follow-symlinks-unless-asked.patch: Don't follow symlinks + unless --follow-symlinks is given. This increases the security + against malicious patches (boo#1142041 CVE-2019-13636). +- pass-the-correct-stat-to-backup-files.patch: Pass the correct + stat to backup files. This bug would occasionally cause backup + files to be missing when all hunks failed to apply (boo#1198106). + ------------------------------------------------------------------- Wed Sep 29 10:33:36 UTC 2021 - Dominique Leuenberger diff --git a/patch.spec b/patch.spec index 62dd689..1da069b 100644 --- a/patch.spec +++ b/patch.spec @@ -1,7 +1,7 @@ # # spec file for package patch # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -35,6 +35,10 @@ Patch6: ed-style-05-minor-cleanups.patch Patch7: ed-style-06-fix-test-failure.patch Patch8: ed-style-07-dont-leak-tmp-file.patch Patch9: ed-style-08-dont-leak-tmp-file-multi.patch +Patch10: fix-swapping-fake-lines-in-pch_swap.patch +Patch11: abort-when-cleaning-up-fails.patch +Patch12: dont-follow-symlinks-unless-asked.patch +Patch13: pass-the-correct-stat-to-backup-files.patch # See bnc#662957. The fix for CVE-2010-4651 breaks the way interdiff was # invoking patch, so interdiff had to be fixed too. Conflicts: patchutils < 0.3.2 @@ -58,6 +62,10 @@ changed files (generated by the diff command) to the original files. %patch7 -p1 %patch8 -p1 %patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 %build export CFLAGS="%{optflags} -Wall -O2 -pipe"