Hi all, I prepared an update of exiv2 for jessie. The patches I prepared applied to the stretch version with only one minor change required.
The main change is the patch for CVE-2018-16336. However, I also included a tweak to the patch for CVE-2018-10958/CVE-2018-10999 based on feedback I received approximately one month after I uploaded the last security update for exiv2: https://github.com/Exiv2/exiv2/issues/302#issuecomment-408640903 I have attached a debdiff from version 0.25-3.1+deb9u1 to 0.25-3.1+deb9u2 for your review and the actual packages are available here: https://people.debian.org/~roberto/ If the package and proposed changes look good, please let me know and I can sign and upload the packages and someone on the security team can publish the DSA. Regards, -Roberto -- Roberto C. Sánchez
diff --git a/debian/changelog b/debian/changelog index 0414fd3..01c9229 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +exiv2 (0.25-3.1+deb9u2) stretch-security; urgency=high + + * Non-maintainer upload by the Security Team. + * Minor adjustment to the patch for CVE-2018-10958 and CVE-2018-10999. The + initial patch was overly restrictive in counting PNG image chunks. + * CVE-2018-16336: remote denial of service (heap-based buffer over-read) via + a crafted image file. + + -- Roberto C. Sanchez <[email protected]> Sat, 20 Oct 2018 22:43:10 -0400 + exiv2 (0.25-3.1+deb9u1) stretch-security; urgency=high * Non-maintainer upload by the Security Team. diff --git a/debian/patches/CVE-2018-10958_10999_1_of_2.patch b/debian/patches/CVE-2018-10958_10999_1_of_2.patch index 75f2ff2..4f227e6 100644 --- a/debian/patches/CVE-2018-10958_10999_1_of_2.patch +++ b/debian/patches/CVE-2018-10958_10999_1_of_2.patch @@ -32,7 +32,7 @@ There must be 2 null separators when we start to analyze the language tag. } else if(type == iTXt_Chunk) { -+ const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_-1], '\0'); ++ const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_], '\0'); + if (nullSeparators < 2) throw Error(58); + // Extract a deflate compressed or uncompressed UTF-8 text chunk diff --git a/debian/patches/CVE-2018-10958_10999_2_of_2.patch b/debian/patches/CVE-2018-10958_10999_2_of_2.patch index 75a2027..06e5ecd 100644 --- a/debian/patches/CVE-2018-10958_10999_2_of_2.patch +++ b/debian/patches/CVE-2018-10958_10999_2_of_2.patch @@ -14,7 +14,7 @@ Subject: [PATCH] Check validity of compressionFlag & compressionMethod @@ -159,14 +159,24 @@ else if(type == iTXt_Chunk) { - const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_-1], '\0'); + const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_], '\0'); - if (nullSeparators < 2) throw Error(58); + if (nullSeparators < 2) throw Error(58, "iTXt chunk: not enough null separators"); diff --git a/debian/patches/CVE-2018-16336.patch b/debian/patches/CVE-2018-16336.patch new file mode 100644 index 0000000..cfd63c5 --- /dev/null +++ b/debian/patches/CVE-2018-16336.patch @@ -0,0 +1,130 @@ +From 35b3e596edacd2437c2c5d3dd2b5c9502626163d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <[email protected]> +Date: Fri, 17 Aug 2018 16:41:05 +0200 +Subject: [PATCH] Add overflow & overread checks to PngChunk::parseTXTChunk() + +This function was creating a lot of new pointers and strings without +properly checking the array bounds. This commit adds several calls +to enforce(), making sure that the pointers stay within bounds. +Strings are now created using the helper function +string_from_unterminated() to prevent overreads in the constructor of +std::string. + +This fixes #400 +--- + src/pngchunk_int.cpp | 63 ++++++++++++++++++++++++++++++---------------------- + 1 file changed, 37 insertions(+), 26 deletions(-) + +--- exiv2-stretch.git.orig/src/pngchunk.cpp ++++ exiv2-stretch.git/src/pngchunk.cpp +@@ -40,6 +40,8 @@ + #include "iptc.hpp" + #include "image.hpp" + #include "error.hpp" ++#include "helper_functions.hpp" ++#include "safe_op.hpp" + + // + standard includes + #include <sstream> +@@ -127,6 +129,8 @@ + + if(type == zTXt_Chunk) + { ++ if (data.size_ < Safe::add(keysize, 2)) throw Error(58); ++ + // Extract a deflate compressed Latin-1 text chunk + + // we get the compression method after the key +@@ -143,11 +147,13 @@ + // compressed string after the compression technique spec + const byte* compressedText = data.pData_ + keysize + 2; + unsigned int compressedTextSize = data.size_ - keysize - 2; ++ if (compressedTextSize >= data.size_) throw Error(58); + + zlibUncompress(compressedText, compressedTextSize, arr); + } + else if(type == tEXt_Chunk) + { ++ if (data.size_ < Safe::add(keysize, 1)) throw Error(58); + // Extract a non-compressed Latin-1 text chunk + + // the text comes after the key, but isn't null terminated +@@ -158,6 +164,7 @@ + } + else if(type == iTXt_Chunk) + { ++ if (data.size_ < Safe::add(keysize, 3)) throw Error(58); + const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_], '\0'); + if (nullSeparators < 2) throw Error(58, "iTXt chunk: not enough null separators"); + +@@ -178,41 +185,43 @@ + } + + // language description string after the compression technique spec +- std::string languageText((const char*)(data.pData_ + keysize + 3)); +- unsigned int languageTextSize = static_cast<unsigned int>(languageText.size()); +- // translated keyword string after the language description +- std::string translatedKeyText((const char*)(data.pData_ + keysize + 3 + languageTextSize +1)); +- unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size()); ++ const size_t languageTextMaxSize = data.size_ - keysize - 3; ++ std::string languageText = ++ string_from_unterminated((const char*)(data.pData_ + Safe::add(keysize, 3)), languageTextMaxSize); ++ const unsigned int languageTextSize = static_cast<unsigned int>(languageText.size()); + +- if ( compressionFlag == 0x00 ) +- { +- // then it's an uncompressed iTXt chunk +-#ifdef DEBUG +- std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n"; +-#endif ++ if (data.size_ < Safe::add(static_cast<unsigned int>(Safe::add(keysize, 4)), languageTextSize)) throw Error(58); ++ // translated keyword string after the language description ++ std::string translatedKeyText = ++ string_from_unterminated((const char*)(data.pData_ + keysize + 3 + languageTextSize + 1), ++ data.size_ - (keysize + 3 + languageTextSize + 1)); ++ const unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size()); ++ ++ if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) { ++ if (Safe::add(static_cast<unsigned int>(keysize + 3 + languageTextSize + 1), ++ Safe::add(translatedKeyTextSize, 1u)) > data.size_) throw Error(58); + +- // the text comes after the translated keyword, but isn't null terminated + const byte* text = data.pData_ + keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1; +- long textsize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1); ++ const long textsize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1); + +- arr.alloc(textsize); +- arr = DataBuf(text, textsize); +- } +- else if ( compressionFlag == 0x01 && compressionMethod == 0x00 ) +- { +- // then it's a zlib compressed iTXt chunk ++ if (compressionFlag == 0x00) { ++ // then it's an uncompressed iTXt chunk + #ifdef DEBUG +- std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n"; ++ std::cout << "Exiv2::PngChunk::parseTXTChunk: We found an uncompressed iTXt field\n"; + #endif + +- // the compressed text comes after the translated keyword, but isn't null terminated +- const byte* compressedText = data.pData_ + keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1; +- long compressedTextSize = data.size_ - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1); ++ arr.alloc(textsize); ++ arr = DataBuf(text, textsize); ++ } else if (compressionFlag == 0x01 && compressionMethod == 0x00) { ++ // then it's a zlib compressed iTXt chunk ++#ifdef DEBUG ++ std::cout << "Exiv2::PngChunk::parseTXTChunk: We found a zlib compressed iTXt field\n"; ++#endif + +- zlibUncompress(compressedText, compressedTextSize, arr); +- } +- else +- { ++ // the compressed text comes after the translated keyword, but isn't null terminated ++ zlibUncompress(text, textsize, arr); ++ } ++ } else { + // then it isn't zlib compressed and we are sunk + #ifdef DEBUG + std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard iTXt compression method.\n"; diff --git a/debian/patches/CVE-2018-16336_prereq.patch b/debian/patches/CVE-2018-16336_prereq.patch new file mode 100644 index 0000000..4a5db64 --- /dev/null +++ b/debian/patches/CVE-2018-16336_prereq.patch @@ -0,0 +1,105 @@ +--- /dev/null ++++ exiv2-stretch.git/src/helper_functions.cpp +@@ -0,0 +1,38 @@ ++// ********************************************************* -*- C++ -*- ++/* ++ * Copyright (C) 2004-2018 Exiv2 authors ++ * This program is part of the Exiv2 distribution. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. ++ */ ++/*! ++ @file helper_functions.cpp ++ @brief A collection of helper functions ++ @author Dan Čermák (D4N) ++ <a href="mailto:[email protected]">[email protected]</a> ++ @date 25-May-18, D4N: created ++ */ ++ ++#include "helper_functions.hpp" ++ ++#include <string.h> ++ ++ ++std::string string_from_unterminated(const char* data, size_t data_length) ++{ ++ const size_t StringLength = strnlen(data, data_length); ++ ++ return std::string(data, StringLength); ++} +--- /dev/null ++++ exiv2-stretch.git/src/helper_functions.hpp +@@ -0,0 +1,49 @@ ++// ********************************************************* -*- C++ -*- ++/* ++ * Copyright (C) 2004-2018 Exiv2 authors ++ * This program is part of the Exiv2 distribution. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. ++ */ ++/*! ++ @file helper_functions.hpp ++ @brief A collection of helper functions ++ @author Dan Čermák (D4N) ++ <a href="mailto:[email protected]">[email protected]</a> ++ @date 25-May-18, D4N: created ++ */ ++#ifndef HELPER_FUNCTIONS_HPP ++#define HELPER_FUNCTIONS_HPP ++ ++#include <string> ++ ++/*! ++ @brief Convert a (potentially not null terminated) array into a ++ std::string. ++ ++ Convert a C style string that may or may not be null terminated safely ++ into a std::string. The string's termination is either set at the first \0 ++ or after data_length characters. ++ ++ @param[in] data A c-string from which the std::string shall be ++ constructed. Does not need to be null terminated. ++ @param[in] data_length An upper bound for the string length (must be at most ++ the allocated length of `buffer`). If no null terminator is found in data, ++ then the resulting std::string will be null terminated at `data_length`. ++ ++ */ ++std::string string_from_unterminated(const char* data, size_t data_length); ++ ++#endif // HELPER_FUNCTIONS_HPP +--- exiv2-stretch.git.orig/src/Makefile ++++ exiv2-stretch.git/src/Makefile +@@ -120,7 +120,8 @@ + value.cpp \ + version.cpp \ + xmp.cpp \ +- xmpsidecar.cpp ++ xmpsidecar.cpp \ ++ helper_functions.cpp + ifdef ENABLE_VIDEO + CCSRC += asfvideo.cpp \ + matroskavideo.cpp \ diff --git a/debian/patches/series b/debian/patches/series index 613c9e6..8f36266 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -10,3 +10,5 @@ CVE-2018-11531_3_of_3.patch CVE-2018-12265_prereq.patch CVE-2018-12265.patch CVE-2018-12264.patch +CVE-2018-16336_prereq.patch +CVE-2018-16336.patch
_______________________________________________ pkg-kde-extras mailing list [email protected] https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-kde-extras
