Skip to contentSkip to conversation

Dpkg: fixing CVE-2014-0471

PATCH New [email protected] 1 participant 3 messages Jun 16, 2014

lore
Share & tools
lore
#0 lore raw

cover Dpkg: fixing CVE-2014-0471

From: Wenzong Fan <[email protected]>

Directory traversal vulnerability in the unpacking functionality in dpkg before 1.15.9, 1.16.x before 1.16.13, and 1.17.x before 1.17.8 allows remote attackers to write arbitrary files via a crafted source package, related to "C-style filename quoting."

The following changes since commit 8e0c54cd0e82ffe120f84f495101cd29e6fd06bf:

bitbake: bb/utils: fix contains_any() (2014-06-12 17:47:59 +0100)

are available in the git repository at:

git://git.pokylinux.org/poky-contrib wenzong/dpkg
http://git.pokylinux.org/cgit.cgi/poky-contrib/log/?h=wenzong/dpkg

Guillem Jover (2):
Dpkg::Source::Patch: Correctly parse C-style diff filenames Dpkg::Source::Patch: Outright reject C-style filenames in patches

 .../dpkg-1.17.4-CVE-2014-0471-CVE-2014-3127.patch  |   49 ++++++++++++
 .../dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471.patch      |   83 ++++++++++++++++++++
 meta/recipes-devtools/dpkg/dpkg_1.17.4.bb          |    2 +
 3 files changed, 134 insertions(+)
 create mode 100644 meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471-CVE-2014-3127.patch
 create mode 100644 meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471.patch
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 1/2 Dpkg::Source::Patch: Correctly parse C-style diff filenames

From: Guillem Jover <[email protected]>

based on: commit a82651188476841d190c58693f95827d61959b51

We need to strip the surrounding quotes, and unescape any escape sequence, so that we check the same files that the patch program will be using, otherwise a malicious package could overpass those checks, and perform directory traversal attacks on source package unpacking.

Fixes CVE-2014-0471

[drop the text for debian/changelog,because it's not suitable
for the veriosn]

---
 .../dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471.patch      |   83 ++++++++++++++++++++
 meta/recipes-devtools/dpkg/dpkg_1.17.4.bb          |    1 +
 2 files changed, 84 insertions(+)
 create mode 100644 meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471.patch
meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471.patch new file +83 -0
new file mode 100644
index 0000000..f5a023a
@@ -0,0 +1,83 @@
+diff -uarN dpkg-1.17.1-org/scripts/Dpkg/Source/Patch.pm dpkg-1.17.1/scripts/Dpkg/Source/Patch.pm
+--- dpkg-1.17.1-org/scripts/Dpkg/Source/Patch.pm	2014-06-05 15:24:07.422446284 +0800
++++ dpkg-1.17.1/scripts/Dpkg/Source/Patch.pm	2014-06-05 15:41:37.746446314 +0800
+@@ -324,14 +324,53 @@
+     return $line;
+ }
+ 
+-# Strip timestamp
+-sub _strip_ts {
+-    my $header = shift;
+-
+-    # Tab is the official separator, it's always used when
+-    # filename contain spaces. Try it first, otherwise strip on space
+-    # if there's no tab
+-    $header =~ s/\s.*// unless ($header =~ s/\t.*//);
++my %ESCAPE = ((
++    'a' => "\a",
++    'b' => "\b",
++    'f' => "\f",
++    'n' => "\n",
++    'r' => "\r",
++    't' => "\t",
++    'v' => "\cK",
++    '\\' => '\\',
++    '"' => '"',
++), (
++    map { sprintf('%03o', $_) => chr($_) } (0..255)
++));
++
++sub _unescape {
++    my ($diff, $str) = @_;
++
++    if (exists $ESCAPE{$str}) {
++        return $ESCAPE{$str};
++    } else {
++        error(_g('diff %s patches file with unknown escape sequence \\%s'),
++              $diff, $str);
++    }
++}
++
++# Fetch the header filename ignoring the optional timestamp
++sub _fetch_filename {
++    my ($diff, $header) = @_;
++
++    # Strip any leading spaces.
++    $header =~ s/^\s+//;
++
++    # Is it a C-style string?
++    if ($header =~ m/^"/) {
++        $header =~ m/^"((?:[^\\"]|\\.)*)"/;
++        error(_g('diff %s patches file with unbalanced quote'), $diff)
++            unless defined $1;
++
++        $header = $1;
++        $header =~ s/\\([0-3][0-7]{2}|.)/_unescape($diff, $1)/eg;
++    } else {
++        # Tab is the official separator, it's always used when
++        # filename contain spaces. Try it first, otherwise strip on space
++        # if there's no tab
++        $header =~ s/\s.*// unless $header =~ s/\t.*//;
++    }
++
+     return $header;
+ }
+ 
+@@ -400,7 +439,7 @@
+ 	unless(s/^--- //) {
+ 	    error(_g("expected ^--- in line %d of diff `%s'"), $., $diff);
+ 	}
+-        $path{old} = $_ = _strip_ts($_);
++	$path{old} = $_ = _fetch_filename($diff, $_);
+ 	$fn{old} = $_ if $_ ne '/dev/null' and s{^[^/]*/+}{$destdir/};
+ 	if (/\.dpkg-orig$/) {
+ 	    error(_g("diff `%s' patches file with name ending .dpkg-orig"), $diff);
+@@ -412,7 +451,7 @@
+ 	unless (s/^\+\+\+ //) {
+ 	    error(_g("line after --- isn't as expected in diff `%s' (line %d)"), $diff, $.);
+ 	}
+-        $path{new} = $_ = _strip_ts($_);
++	$path{new} = $_ = _fetch_filename($diff, $_);
+ 	$fn{new} = $_ if $_ ne '/dev/null' and s{^[^/]*/+}{$destdir/};
+ 
+ 	unless (defined $fn{old} or defined $fn{new}) {
meta/recipes-devtools/dpkg/dpkg_1.17.4.bb +1 -0
index 5507352..48e1394 100644
@@ -12,6 +12,7 @@ SRC_URI += "file://noman.patch \
             file://dpkg-configure.service \
             file://glibc2.5-sync_file_range.patch \
             file://no-vla-warning.patch \
+            file://dpkg-1.17.4-CVE-2014-0471.patch \
            "
 
 SRC_URI[md5sum] = "cc25086e1e3bd9512a95f14cfe9002e1"
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 2/2 Dpkg::Source::Patch: Outright reject C-style filenames in patches

In reply to [email protected]

From: Guillem Jover <[email protected]>

based on: commit a12eb58959d0a10584a428f4a3103a49204c410f

Because patch only started recognizing C-style filenames in diffs in version 2.7, it's not safe to assume one behaviour or the other, as the system might or might not have a recent enough version, or a GNU patch program at all. There's also no reason we should be supporting this kind of strange encoded filenames in patches, when we have not done so up to now.

Let's just ban these types of diffs and be done with it.

Fixes CVE-2014-0471
Closes #746306

[drop the text for debian/changelog,because it's not suitable for the veriosn]

---
 .../dpkg-1.17.4-CVE-2014-0471-CVE-2014-3127.patch  |   49 ++++++++++++++++++++
 meta/recipes-devtools/dpkg/dpkg_1.17.4.bb          |    1 +
 2 files changed, 50 insertions(+)
 create mode 100644 meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471-CVE-2014-3127.patch
meta/recipes-devtools/dpkg/dpkg/dpkg-1.17.4-CVE-2014-0471-CVE-2014-3127.patch new file +49 -0
new file mode 100644
index 0000000..d49b073
@@ -0,0 +1,49 @@
+diff -uarN dpkg-1.17.1-org/scripts/Dpkg/Source/Patch.pm dpkg-1.17.1/scripts/Dpkg/Source/Patch.pm
+--- dpkg-1.17.1-org/scripts/Dpkg/Source/Patch.pm	2014-06-05 16:32:41.765446564 +0800
++++ dpkg-1.17.1/scripts/Dpkg/Source/Patch.pm	2014-06-05 16:37:21.461446359 +0800
+@@ -324,31 +324,6 @@
+     return $line;
+ }
+ 
+-my %ESCAPE = ((
+-    'a' => "\a",
+-    'b' => "\b",
+-    'f' => "\f",
+-    'n' => "\n",
+-    'r' => "\r",
+-    't' => "\t",
+-    'v' => "\cK",
+-    '\\' => '\\',
+-    '"' => '"',
+-), (
+-    map { sprintf('%03o', $_) => chr($_) } (0..255)
+-));
+-
+-sub _unescape {
+-    my ($diff, $str) = @_;
+-
+-    if (exists $ESCAPE{$str}) {
+-        return $ESCAPE{$str};
+-    } else {
+-        error(_g('diff %s patches file with unknown escape sequence \\%s'),
+-              $diff, $str);
+-    }
+-}
+-
+ # Fetch the header filename ignoring the optional timestamp
+ sub _fetch_filename {
+     my ($diff, $header) = @_;
+@@ -358,12 +333,7 @@
+ 
+     # Is it a C-style string?
+     if ($header =~ m/^"/) {
+-        $header =~ m/^"((?:[^\\"]|\\.)*)"/;
+-        error(_g('diff %s patches file with unbalanced quote'), $diff)
+-            unless defined $1;
+-
+-        $header = $1;
+-        $header =~ s/\\([0-3][0-7]{2}|.)/_unescape($diff, $1)/eg;
++	error(_g('diff %s patches file with C-style encoded filename'), $diff);
+     } else {
+         # Tab is the official separator, it's always used when
+         # filename contain spaces. Try it first, otherwise strip on space
meta/recipes-devtools/dpkg/dpkg_1.17.4.bb +1 -0
index 48e1394..83526f3 100644
@@ -13,6 +13,7 @@ SRC_URI += "file://noman.patch \
             file://glibc2.5-sync_file_range.patch \
             file://no-vla-warning.patch \
             file://dpkg-1.17.4-CVE-2014-0471.patch \
+            file://dpkg-1.17.4-CVE-2014-0471-CVE-2014-3127.patch \
            "
 
 SRC_URI[md5sum] = "cc25086e1e3bd9512a95f14cfe9002e1"
Signature · 1 line
1.7.9.5