Blame SOURCES/xz-5.2.4-cve-2022-1271.patch

e0aaaf
From 69d1b3fc29677af8ade8dc15dba83f0589cb63d6 Mon Sep 17 00:00:00 2001
e0aaaf
From: Lasse Collin <lasse.collin@tukaani.org>
e0aaaf
Date: Tue, 29 Mar 2022 19:19:12 +0300
e0aaaf
Subject: [PATCH] xzgrep: Fix escaping of malicious filenames (ZDI-CAN-16587).
e0aaaf
e0aaaf
Malicious filenames can make xzgrep to write to arbitrary files
e0aaaf
or (with a GNU sed extension) lead to arbitrary code execution.
e0aaaf
e0aaaf
xzgrep from XZ Utils versions up to and including 5.2.5 are
e0aaaf
affected. 5.3.1alpha and 5.3.2alpha are affected as well.
e0aaaf
This patch works for all of them.
e0aaaf
e0aaaf
This bug was inherited from gzip's zgrep. gzip 1.12 includes
e0aaaf
a fix for zgrep.
e0aaaf
e0aaaf
The issue with the old sed script is that with multiple newlines,
e0aaaf
the N-command will read the second line of input, then the
e0aaaf
s-commands will be skipped because it's not the end of the
e0aaaf
file yet, then a new sed cycle starts and the pattern space
e0aaaf
is printed and emptied. So only the last line or two get escaped.
e0aaaf
e0aaaf
One way to fix this would be to read all lines into the pattern
e0aaaf
space first. However, the included fix is even simpler: All lines
e0aaaf
except the last line get a backslash appended at the end. To ensure
e0aaaf
that shell command substitution doesn't eat a possible trailing
e0aaaf
newline, a colon is appended to the filename before escaping.
e0aaaf
The colon is later used to separate the filename from the grep
e0aaaf
output so it is fine to add it here instead of a few lines later.
e0aaaf
e0aaaf
The old code also wasn't POSIX compliant as it used \n in the
e0aaaf
replacement section of the s-command. Using \<newline> is the
e0aaaf
POSIX compatible method.
e0aaaf
e0aaaf
LC_ALL=C was added to the two critical sed commands. POSIX sed
e0aaaf
manual recommends it when using sed to manipulate pathnames
e0aaaf
because in other locales invalid multibyte sequences might
e0aaaf
cause issues with some sed implementations. In case of GNU sed,
e0aaaf
these particular sed scripts wouldn't have such problems but some
e0aaaf
other scripts could have, see:
e0aaaf
e0aaaf
    info '(sed)Locale Considerations'
e0aaaf
e0aaaf
This vulnerability was discovered by:
e0aaaf
cleemy desu wayo working with Trend Micro Zero Day Initiative
e0aaaf
e0aaaf
Thanks to Jim Meyering and Paul Eggert discussing the different
e0aaaf
ways to fix this and for coordinating the patch release schedule
e0aaaf
with gzip.
e0aaaf
---
e0aaaf
 src/scripts/xzgrep.in | 20 ++++++++++++--------
e0aaaf
 1 file changed, 12 insertions(+), 8 deletions(-)
e0aaaf
e0aaaf
diff --git a/src/scripts/xzgrep.in b/src/scripts/xzgrep.in
e0aaaf
index b180936..e5186ba 100644
e0aaaf
--- a/src/scripts/xzgrep.in
e0aaaf
+++ b/src/scripts/xzgrep.in
e0aaaf
@@ -180,22 +180,26 @@ for i; do
e0aaaf
          { test $# -eq 1 || test $no_filename -eq 1; }; then
e0aaaf
       eval "$grep"
e0aaaf
     else
e0aaaf
+      # Append a colon so that the last character will never be a newline
e0aaaf
+      # which would otherwise get lost in shell command substitution.
e0aaaf
+      i="$i:"
e0aaaf
+
e0aaaf
+      # Escape & \ | and newlines only if such characters are present
e0aaaf
+      # (speed optimization).
e0aaaf
       case $i in
e0aaaf
       (*'
e0aaaf
 '* | *'&'* | *'\'* | *'|'*)
e0aaaf
-        i=$(printf '%s\n' "$i" |
e0aaaf
-            sed '
e0aaaf
-              $!N
e0aaaf
-              $s/[&\|]/\\&/g
e0aaaf
-              $s/\n/\\n/g
e0aaaf
-            ');;
e0aaaf
+        i=$(printf '%s\n' "$i" | LC_ALL=C sed 's/[&\|]/\\&/;; $!s/$/\\/');;
e0aaaf
       esac
e0aaaf
-      sed_script="s|^|$i:|"
e0aaaf
+
e0aaaf
+      # $i already ends with a colon so don't add it here.
e0aaaf
+      sed_script="s|^|$i|"
e0aaaf
 
e0aaaf
       # Fail if grep or sed fails.
e0aaaf
       r=$(
e0aaaf
         exec 4>&1
e0aaaf
-        (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&-
e0aaaf
+        (eval "$grep" 4>&-; echo $? >&4) 3>&- |
e0aaaf
+            LC_ALL=C sed "$sed_script" >&3 4>&-
e0aaaf
       ) || r=2
e0aaaf
       exit $r
e0aaaf
     fi >&3 5>&-
e0aaaf
-- 
e0aaaf
2.35.1
e0aaaf