gnu: upx: Fix CVE-2017-15056.

* gnu/packages/patches/upx-protect-against-bad-crafted-input.patch: New file.
* gnu/packages/compression.scm (upx)[source]: Use it.
* gnu/local.mk (dist_patch_DATA): Add it.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Pierre Neidhardt 2018-06-16 16:54:53 +02:00 committed by Ludovic Courtès
parent ed2ae0dc7f
commit a14de83213
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
3 changed files with 104 additions and 1 deletions

View file

@ -1157,6 +1157,7 @@ dist_patch_DATA = \
%D%/packages/patches/ustr-fix-build-with-gcc-5.patch \ %D%/packages/patches/ustr-fix-build-with-gcc-5.patch \
%D%/packages/patches/util-linux-tests.patch \ %D%/packages/patches/util-linux-tests.patch \
%D%/packages/patches/upower-builddir.patch \ %D%/packages/patches/upower-builddir.patch \
%D%/packages/patches/upx-fix-CVE-2017-15056.patch \
%D%/packages/patches/valgrind-enable-arm.patch \ %D%/packages/patches/valgrind-enable-arm.patch \
%D%/packages/patches/valgrind-glibc-compat.patch \ %D%/packages/patches/valgrind-glibc-compat.patch \
%D%/packages/patches/vinagre-revert-1.patch \ %D%/packages/patches/vinagre-revert-1.patch \

View file

@ -2209,7 +2209,8 @@ (define-public upx
version "/" name "-" version "-src.tar.xz")) version "/" name "-" version "-src.tar.xz"))
(sha256 (sha256
(base32 (base32
"08anybdliqsbsl6x835iwzljahnm9i7v26icdjkcv33xmk6p5vw1")))) "08anybdliqsbsl6x835iwzljahnm9i7v26icdjkcv33xmk6p5vw1"))
(patches (search-patches "upx-fix-CVE-2017-15056.patch"))))
(build-system gnu-build-system) (build-system gnu-build-system)
(native-inputs `(("perl" ,perl) (native-inputs `(("perl" ,perl)
("ucl" ,ucl))) ("ucl" ,ucl)))
@ -2241,6 +2242,11 @@ (define-public upx
#t)) #t))
))) )))
(home-page "https://upx.github.io/") (home-page "https://upx.github.io/")
;; CVE-2017-16869 is about Mach-O files which is not of a big concern for Guix.
;; See https://github.com/upx/upx/issues/146 and
;; https://nvd.nist.gov/vuln/detail?vulnId=CVE-2017-16869.
;; The issue will be fixed after version 3.94.
(properties `((lint-hidden-cve . ("CVE-2017-16869"))))
(synopsis "Compression tool for executables") (synopsis "Compression tool for executables")
(description (description
"The Ultimate Packer for eXecutables (UPX) is an executable file "The Ultimate Packer for eXecutables (UPX) is an executable file

View file

@ -0,0 +1,96 @@
From 3e0c2966dffb5dadb512a476ef4be3d0cc51c2be Mon Sep 17 00:00:00 2001
From: Pierre Neidhardt <ambrevar@gmail.com>
Date: Sat, 16 Jun 2018 16:35:00 +0200
Subject: [PATCH] Protect against bad crafted input
Also check for wrap-around when checking oversize involving e_shoff and e_shnum.
raised by https://github.com/upx/upx/pull/190
modified: p_lx_elf.cpp
---
src/p_lx_elf.cpp | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp
index 822a7652..41e805ee 100644
--- a/src/p_lx_elf.cpp
+++ b/src/p_lx_elf.cpp
@@ -235,8 +235,17 @@ PackLinuxElf32::PackLinuxElf32help1(InputFile *f)
sz_phdrs = 0;
return;
}
+ if (0==e_phnum) throwCantUnpack("0==e_phnum");
e_phoff = get_te32(&ehdri.e_phoff);
+ unsigned const last_Phdr = e_phoff + e_phnum * sizeof(Elf32_Phdr);
+ if (last_Phdr < e_phoff || (unsigned long)file_size < last_Phdr) {
+ throwCantUnpack("bad e_phoff");
+ }
e_shoff = get_te32(&ehdri.e_shoff);
+ unsigned const last_Shdr = e_shoff + e_shnum * sizeof(Elf32_Shdr);
+ if (last_Shdr < e_shoff || (unsigned long)file_size < last_Shdr) {
+ throwCantUnpack("bad e_shoff");
+ }
sz_phdrs = e_phnum * e_phentsize;
if (f && Elf32_Ehdr::ET_DYN!=e_type) {
@@ -599,8 +608,17 @@ PackLinuxElf64::PackLinuxElf64help1(InputFile *f)
sz_phdrs = 0;
return;
}
+ if (0==e_phnum) throwCantUnpack("0==e_phnum");
e_phoff = get_te64(&ehdri.e_phoff);
+ upx_uint64_t const last_Phdr = e_phoff + e_phnum * sizeof(Elf64_Phdr);
+ if (last_Phdr < e_phoff || (unsigned long)file_size < last_Phdr) {
+ throwCantUnpack("bad e_phoff");
+ }
e_shoff = get_te64(&ehdri.e_shoff);
+ upx_uint64_t const last_Shdr = e_shoff + e_shnum * sizeof(Elf64_Shdr);
+ if (last_Shdr < e_shoff || (unsigned long)file_size < last_Shdr) {
+ throwCantUnpack("bad e_shoff");
+ }
sz_phdrs = e_phnum * e_phentsize;
if (f && Elf64_Ehdr::ET_DYN!=e_type) {
@@ -3763,6 +3781,9 @@ void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft)
void PackLinuxElf64::unpack(OutputFile *fo)
{
+ if (e_phoff != sizeof(Elf64_Ehdr)) {// Phdrs not contiguous with Ehdr
+ throwCantUnpack("bad e_phoff");
+ }
unsigned const c_phnum = get_te16(&ehdri.e_phnum);
upx_uint64_t old_data_off = 0;
upx_uint64_t old_data_len = 0;
@@ -3828,6 +3849,9 @@ void PackLinuxElf64::unpack(OutputFile *fo)
unsigned total_out = 0;
unsigned c_adler = upx_adler32(NULL, 0);
unsigned u_adler = upx_adler32(NULL, 0);
+ if ((MAX_ELF_HDR - sizeof(Elf64_Ehdr))/sizeof(Elf64_Phdr) < u_phnum) {
+ throwCantUnpack("bad compressed e_phnum");
+ }
// Packed ET_EXE has no PT_DYNAMIC.
// Packed ET_DYN has original PT_DYNAMIC for info needed by rtld.
@@ -4383,6 +4407,9 @@ Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const
void PackLinuxElf32::unpack(OutputFile *fo)
{
+ if (e_phoff != sizeof(Elf32_Ehdr)) {// Phdrs not contiguous with Ehdr
+ throwCantUnpack("bad e_phoff");
+ }
unsigned const c_phnum = get_te16(&ehdri.e_phnum);
unsigned old_data_off = 0;
unsigned old_data_len = 0;
@@ -4449,6 +4476,9 @@ void PackLinuxElf32::unpack(OutputFile *fo)
unsigned total_out = 0;
unsigned c_adler = upx_adler32(NULL, 0);
unsigned u_adler = upx_adler32(NULL, 0);
+ if ((MAX_ELF_HDR - sizeof(Elf32_Ehdr))/sizeof(Elf32_Phdr) < u_phnum) {
+ throwCantUnpack("bad compressed e_phnum");
+ }
// Packed ET_EXE has no PT_DYNAMIC.
// Packed ET_DYN has original PT_DYNAMIC for info needed by rtld.
--
2.17.0