diff -Nru icu-4.8.1.1/debian/changelog icu-4.8.1.1/debian/changelog --- icu-4.8.1.1/debian/changelog 2012-06-05 18:27:27.000000000 +0000 +++ icu-4.8.1.1/debian/changelog 2013-10-10 14:36:25.000000000 +0000 @@ -1,3 +1,18 @@ +icu (4.8.1.1-8ubuntu0.1) quantal-security; urgency=low + + * SECURITY UPDATE: denial of service and possible code execution via + race condition. + - debian/patches/CVE-2013-0900.patch: fix thread safety issue in + source/common/locid.cpp, source/common/unicode/locid.h. + - CVE-2013-0900 + * SECURITY UPDATE: denial of service and possible code execution via + use after free. + - debian/patches/CVE-2013-2924.patch: check lengths in + source/i18n/csrucode.cpp. + - CVE-2013-2924 + + -- Marc Deslauriers Thu, 10 Oct 2013 10:33:37 -0400 + icu (4.8.1.1-8) unstable; urgency=low * Switch hardening back to hardening-wrapper again since otherwise some diff -Nru icu-4.8.1.1/debian/control icu-4.8.1.1/debian/control --- icu-4.8.1.1/debian/control 2012-06-05 18:25:52.000000000 +0000 +++ icu-4.8.1.1/debian/control 2013-10-10 14:36:48.000000000 +0000 @@ -1,7 +1,8 @@ Source: icu Section: libs Priority: optional -Maintainer: Jay Berkenbilt +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Jay Berkenbilt Standards-Version: 3.9.3 Build-Depends: cdbs (>= 0.4.93~), debhelper (>> 9~), dpkg-dev (>= 1.16.1~), doxygen (>= 1.7.1), hardening-wrapper Homepage: http://www.icu-project.org diff -Nru icu-4.8.1.1/debian/patches/CVE-2013-0900.patch icu-4.8.1.1/debian/patches/CVE-2013-0900.patch --- icu-4.8.1.1/debian/patches/CVE-2013-0900.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-4.8.1.1/debian/patches/CVE-2013-0900.patch 2013-10-10 14:33:18.000000000 +0000 @@ -0,0 +1,296 @@ +Description: CVE-2013-0900: Race condition in ICU. + Credit to Google Chrome Security Team (Inferno) + Patch taken from backport done by Fedora 17 +Origin: upstream, http://www.icu-project.org/trac/changeset/32865, http://www.icu-project.org/trac/changeset/32908 +Bug-Debian: http://bugs.debian.org/702346 +Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2013-0900 + +Index: icu-4.8.1.1/source/common/locid.cpp +=================================================================== +--- icu-4.8.1.1.orig/source/common/locid.cpp 2013-03-21 11:21:45.053153118 -0400 ++++ icu-4.8.1.1/source/common/locid.cpp 2013-03-21 11:21:45.029153121 -0400 +@@ -1,6 +1,6 @@ + /* + ********************************************************************** +- * Copyright (C) 1997-2010, International Business Machines ++ * Copyright (C) 1997-2012, International Business Machines + * Corporation and others. All Rights Reserved. + ********************************************************************** + * +@@ -32,6 +32,7 @@ + + #include "unicode/locid.h" + #include "unicode/uloc.h" ++#include "mutex.h" + #include "umutex.h" + #include "uassert.h" + #include "cmemory.h" +@@ -41,6 +42,21 @@ + + #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) + ++U_CDECL_BEGIN ++static UBool U_CALLCONV locale_cleanup(void); ++U_CDECL_END ++ ++U_NAMESPACE_BEGIN ++ ++static U_NAMESPACE_QUALIFIER Locale *gLocaleCache = NULL; ++ ++// gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale. ++static UMTX gDefaultLocaleMutex = 0; ++static UHashtable *gDefaultLocalesHashT = NULL; ++static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale = NULL; ++ ++U_NAMESPACE_END ++ + typedef enum ELocalePos { + eENGLISH, + eFRENCH, +@@ -75,10 +91,6 @@ + UBool valuesToo, + UErrorCode *status); + +-static U_NAMESPACE_QUALIFIER Locale *gLocaleCache = NULL; +-static U_NAMESPACE_QUALIFIER Locale *gDefaultLocale = NULL; +-static UHashtable *gDefaultLocalesHashT = NULL; +- + U_CDECL_BEGIN + // + // Deleter function for Locales owned by the default Locale hash table/ +@@ -100,24 +112,19 @@ + if (gDefaultLocalesHashT) { + uhash_close(gDefaultLocalesHashT); // Automatically deletes all elements, using deleter func. + gDefaultLocalesHashT = NULL; ++ gDefaultLocale = NULL; + } +- else if (gDefaultLocale) { +- // The cache wasn't created, and only one default locale was created. +- delete gDefaultLocale; +- } +- gDefaultLocale = NULL; + + return TRUE; + } + U_CDECL_END + + U_NAMESPACE_BEGIN +-// +-// locale_set_default_internal. +-// +-void locale_set_default_internal(const char *id) +-{ +- UErrorCode status = U_ZERO_ERROR; ++ ++Locale *locale_set_default_internal(const char *id, UErrorCode& status) { ++ // Synchronize this entire function. ++ Mutex lock(&gDefaultLocaleMutex); ++ + UBool canonicalize = FALSE; + + // If given a NULL string for the locale id, grab the default +@@ -125,17 +132,10 @@ + // (Different from most other locale APIs, where a null name means use + // the current ICU default locale.) + if (id == NULL) { +- umtx_lock(NULL); +- id = uprv_getDefaultLocaleID(); +- umtx_unlock(NULL); ++ id = uprv_getDefaultLocaleID(); // This function not thread safe? TODO: verify. + canonicalize = TRUE; // always canonicalize host ID + } + +- // put the locale id into a canonical form, +- // in preparation for looking up this locale in the hash table of +- // already-created locale objects. +- // +- status = U_ZERO_ERROR; + char localeNameBuf[512]; + + if (canonicalize) { +@@ -146,100 +146,37 @@ + localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of + // a long name filling the buffer. + // (long names are truncated.) ++ // ++ if (U_FAILURE(status)) { ++ return gDefaultLocale; ++ } + +- // Lazy creation of the hash table itself, if needed. +- UBool isOnlyLocale; +- UMTX_CHECK(NULL, (gDefaultLocale == NULL), isOnlyLocale); +- if (isOnlyLocale) { +- // We haven't seen this locale id before. +- // Create a new Locale object for it. +- Locale *newFirstDefault = new Locale(Locale::eBOGUS); +- if (newFirstDefault == NULL) { +- // No way to report errors from here. +- return; +- } +- newFirstDefault->init(localeNameBuf, FALSE); +- umtx_lock(NULL); +- if (gDefaultLocale == NULL) { +- gDefaultLocale = newFirstDefault; // Assignment to gDefaultLocale must happen inside mutex +- newFirstDefault = NULL; +- ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); +- } +- // Else some other thread raced us through here, and set the new Locale. +- // Use the hash table next. +- umtx_unlock(NULL); +- if (newFirstDefault == NULL) { +- // We were successful in setting the locale, and we were the first one to set it. +- return; +- } +- // else start using the hash table. +- } +- +- // Lazy creation of the hash table itself, if needed. +- UBool hashTableNeedsInit; +- UMTX_CHECK(NULL, (gDefaultLocalesHashT == NULL), hashTableNeedsInit); +- if (hashTableNeedsInit) { +- status = U_ZERO_ERROR; +- UHashtable *tHashTable = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); ++ if (gDefaultLocalesHashT == NULL) { ++ gDefaultLocalesHashT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); + if (U_FAILURE(status)) { +- return; +- } +- uhash_setValueDeleter(tHashTable, deleteLocale); +- umtx_lock(NULL); +- if (gDefaultLocalesHashT == NULL) { +- gDefaultLocalesHashT = tHashTable; +- ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); +- } else { +- uhash_close(tHashTable); +- hashTableNeedsInit = FALSE; ++ return gDefaultLocale; + } +- umtx_unlock(NULL); ++ uhash_setValueDeleter(gDefaultLocalesHashT, deleteLocale); ++ ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); + } + +- // Hash table lookup, key is the locale full name +- umtx_lock(NULL); + Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf); +- if (newDefault != NULL) { +- // We have the requested locale in the hash table already. +- // Just set it as default. Inside the mutex lock, for those troublesome processors. +- gDefaultLocale = newDefault; +- umtx_unlock(NULL); +- } else { +- umtx_unlock(NULL); +- // We haven't seen this locale id before. +- // Create a new Locale object for it. ++ if (newDefault == NULL) { + newDefault = new Locale(Locale::eBOGUS); + if (newDefault == NULL) { +- // No way to report errors from here. +- return; ++ status = U_MEMORY_ALLOCATION_ERROR; ++ return gDefaultLocale; + } + newDefault->init(localeNameBuf, FALSE); +- +- // Add newly created Locale to the hash table of default Locales +- const char *key = newDefault->getName(); +- U_ASSERT(uprv_strcmp(key, localeNameBuf) == 0); +- umtx_lock(NULL); +- Locale *hashTableVal = (Locale *)uhash_get(gDefaultLocalesHashT, key); +- if (hashTableVal == NULL) { +- if (hashTableNeedsInit) { +- // This is the second request to set the locale. +- // Cache the first one. +- uhash_put(gDefaultLocalesHashT, (void *)gDefaultLocale->getName(), gDefaultLocale, &status); +- } +- uhash_put(gDefaultLocalesHashT, (void *)key, newDefault, &status); +- gDefaultLocale = newDefault; +- // ignore errors from hash table insert. (Couldn't do anything anyway) +- // We can still set the default Locale, +- // it just wont be cached, and will eventually leak. +- } else { +- // Some other thread raced us through here, and got the new Locale +- // into the hash table before us. Use that one. +- gDefaultLocale = hashTableVal; // Assignment to gDefaultLocale must happen inside mutex +- delete newDefault; ++ uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status); ++ if (U_FAILURE(status)) { ++ return gDefaultLocale; + } +- umtx_unlock(NULL); + } ++ gDefaultLocale = newDefault; ++ return gDefaultLocale; + } ++ + U_NAMESPACE_END + + /* sfb 07/21/99 */ +@@ -247,7 +184,8 @@ + locale_set_default(const char *id) + { + U_NAMESPACE_USE +- locale_set_default_internal(id); ++ UErrorCode status = U_ZERO_ERROR; ++ locale_set_default_internal(id, status); + } + /* end */ + +@@ -255,7 +193,6 @@ + locale_get_default(void) + { + U_NAMESPACE_USE +- + return Locale::getDefault().getName(); + } + +@@ -661,19 +598,14 @@ + const Locale& U_EXPORT2 + Locale::getDefault() + { +- const Locale *retLocale; +- UMTX_CHECK(NULL, gDefaultLocale, retLocale); +- if (retLocale == NULL) { +- locale_set_default_internal(NULL); +- umtx_lock(NULL); +- // Need a mutex in case some other thread set a new +- // default inbetween when we set and when we get the new default. For +- // processors with weak memory coherency, we might not otherwise see all +- // of the newly created new default locale. +- retLocale = gDefaultLocale; +- umtx_unlock(NULL); ++ { ++ Mutex lock(&gDefaultLocaleMutex); ++ if (gDefaultLocale != NULL) { ++ return *gDefaultLocale; ++ } + } +- return *retLocale; ++ UErrorCode status = U_ZERO_ERROR; ++ return *locale_set_default_internal(NULL, status); + } + + +@@ -690,7 +622,7 @@ + * This is a convenient way to access the default locale caching mechanisms. + */ + const char *localeID = newLocale.getName(); +- locale_set_default_internal(localeID); ++ locale_set_default_internal(localeID, status); + } + + Locale U_EXPORT2 +Index: icu-4.8.1.1/source/common/unicode/locid.h +=================================================================== +--- icu-4.8.1.1.orig/source/common/unicode/locid.h 2013-03-21 11:21:45.053153118 -0400 ++++ icu-4.8.1.1/source/common/unicode/locid.h 2013-03-21 11:21:45.041153115 -0400 +@@ -732,7 +732,7 @@ + * A friend to allow the default locale to be set by either the C or C++ API. + * @internal + */ +- friend void locale_set_default_internal(const char *); ++ friend Locale *locale_set_default_internal(const char *, UErrorCode& status); + }; + + inline UBool diff -Nru icu-4.8.1.1/debian/patches/CVE-2013-2924.patch icu-4.8.1.1/debian/patches/CVE-2013-2924.patch --- icu-4.8.1.1/debian/patches/CVE-2013-2924.patch 1970-01-01 00:00:00.000000000 +0000 +++ icu-4.8.1.1/debian/patches/CVE-2013-2924.patch 2013-10-10 14:33:32.000000000 +0000 @@ -0,0 +1,39 @@ +Description: fix denial of service and possible code execution via use after free. +Origin: backport, https://ssl.icu-project.org/trac/changeset/34076 +Bug: http://bugs.icu-project.org/trac/ticket/10318 + +Index: icu-4.8.1.1/source/i18n/csrucode.cpp +=================================================================== +--- icu-4.8.1.1.orig/source/i18n/csrucode.cpp 2011-10-18 19:12:16.000000000 -0400 ++++ icu-4.8.1.1/source/i18n/csrucode.cpp 2013-10-10 10:27:43.982868070 -0400 +@@ -31,8 +31,9 @@ + int32_t CharsetRecog_UTF_16_BE::match(InputText* textIn) + { + const uint8_t *input = textIn->fRawInput; ++ int32_t length = textIn->fRawLength; + +- if (input[0] == 0xFE && input[1] == 0xFF) { ++ if (length >=2 && input[0] == 0xFE && input[1] == 0xFF) { + return 100; + } + +@@ -53,8 +54,9 @@ + int32_t CharsetRecog_UTF_16_LE::match(InputText* textIn) + { + const uint8_t *input = textIn->fRawInput; ++ int32_t length = textIn->fRawLength; + +- if (input[0] == 0xFF && input[1] == 0xFE && (input[2] != 0x00 || input[3] != 0x00)) { ++ if (length >= 4 && input[0] == 0xFF && input[1] == 0xFE && (input[2] != 0x00 || input[3] != 0x00)) { + return 100; + } + +@@ -76,7 +78,7 @@ + bool hasBOM = FALSE; + int32_t confidence = 0; + +- if (getChar(input, 0) == 0x0000FEFFUL) { ++ if (limit > 0 && getChar(input, 0) == 0x0000FEFFUL) { + hasBOM = TRUE; + } + diff -Nru icu-4.8.1.1/debian/patches/series icu-4.8.1.1/debian/patches/series --- icu-4.8.1.1/debian/patches/series 2012-05-24 17:52:17.000000000 +0000 +++ icu-4.8.1.1/debian/patches/series 2013-10-10 14:33:32.000000000 +0000 @@ -8,3 +8,5 @@ pathmax.patch CVE-2011-4599.patch indic-ccmp.patch +CVE-2013-0900.patch +CVE-2013-2924.patch