summaryrefslogtreecommitdiff
path: root/icu
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2013-03-07 00:42:48 +0100
committerEike Rathke <erack@redhat.com>2013-03-07 00:46:25 +0100
commit94147f6ea2de2ace33fc3212f16ee441385cb373 (patch)
tree90e63828f956d2ce03d58eadcc42c9ff55c65481 /icu
parent303ff2493ba479d4b52874b8e5afa4491d9cec11 (diff)
resolved rhbz#918168 ICU: CVE-2013-0900 race condition allows DoS
Upstream changes https://ssl.icu-project.org/trac/changeset/32865 https://ssl.icu-project.org/trac/changeset/32908 See also https://bugzilla.redhat.com/show_bug.cgi?id=918167 Plus changed UMutex to UMTX to make these compile in icu49. Change-Id: Ib5dba7085e6b2dd3925c0c220b5d264e4c7bb4c8
Diffstat (limited to 'icu')
-rw-r--r--icu/UnpackedTarball_icu.mk2
-rw-r--r--icu/icu4c-CVE-2013-0900_umutex.patch12
-rw-r--r--icu/icu4c.9737.CVE-2013-0900_changesets_32865_32908.patch291
3 files changed, 305 insertions, 0 deletions
diff --git a/icu/UnpackedTarball_icu.mk b/icu/UnpackedTarball_icu.mk
index e1ace9c4b3b7..14da6d5d1cf2 100644
--- a/icu/UnpackedTarball_icu.mk
+++ b/icu/UnpackedTarball_icu.mk
@@ -25,6 +25,8 @@ $(eval $(call gb_UnpackedTarball_add_patches,icu,\
icu/icu4c-solarisgcc.patch \
icu/icu4c-mkdir.patch \
icu/icu4c-buffer-overflow.patch \
+ icu/icu4c.9737.CVE-2013-0900_changesets_32865_32908.patch \
+ icu/icu4c-CVE-2013-0900_umutex.patch \
icu/icu4c-$(if $(filter ANDROID,$(OS)),android,rpath).patch \
))
diff --git a/icu/icu4c-CVE-2013-0900_umutex.patch b/icu/icu4c-CVE-2013-0900_umutex.patch
new file mode 100644
index 000000000000..e195c5cade2f
--- /dev/null
+++ b/icu/icu4c-CVE-2013-0900_umutex.patch
@@ -0,0 +1,12 @@
+diff -ruN icu.orig/source/common/locid.cpp icu/source/common/locid.cpp
+--- build/icu.orig/source/common/locid.cpp 2013-03-06 21:27:35.170696967 +0100
++++ build/icu/source/common/locid.cpp 2013-03-06 21:29:47.711378977 +0100
+@@ -53,7 +53,7 @@
+ static Locale *gLocaleCache = NULL;
+
+ // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
+-static UMutex gDefaultLocaleMutex = U_MUTEX_INITIALIZER;
++static UMTX gDefaultLocaleMutex = NULL;
+ static UHashtable *gDefaultLocalesHashT = NULL;
+ static Locale *gDefaultLocale = NULL;
+
diff --git a/icu/icu4c.9737.CVE-2013-0900_changesets_32865_32908.patch b/icu/icu4c.9737.CVE-2013-0900_changesets_32865_32908.patch
new file mode 100644
index 000000000000..8010f09218a8
--- /dev/null
+++ b/icu/icu4c.9737.CVE-2013-0900_changesets_32865_32908.patch
@@ -0,0 +1,291 @@
+Squashed into one:
+https://ssl.icu-project.org/trac/changeset/32865
+https://ssl.icu-project.org/trac/changeset/32908
+
+diff -ruN icu.orig/source/common/locid.cpp icu/source/common/locid.cpp
+--- build/icu.orig/source/common/locid.cpp 2012-04-05 22:46:14.000000000 +0200
++++ build/icu/source/common/locid.cpp 2013-03-05 21:54:11.974608225 +0100
+@@ -1,6 +1,6 @@
+ /*
+ **********************************************************************
+- * Copyright (C) 1997-2011, International Business Machines
++ * Copyright (C) 1997-2012, International Business Machines
+ * Corporation and others. All Rights Reserved.
+ **********************************************************************
+ *
+@@ -33,6 +33,7 @@
+ #include "unicode/locid.h"
+ #include "unicode/uloc.h"
+ #include "putilimp.h"
++#include "mutex.h"
+ #include "umutex.h"
+ #include "uassert.h"
+ #include "cmemory.h"
+@@ -43,6 +44,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 Locale *gLocaleCache = NULL;
++
++// gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
++static UMutex gDefaultLocaleMutex = U_MUTEX_INITIALIZER;
++static UHashtable *gDefaultLocalesHashT = NULL;
++static Locale *gDefaultLocale = NULL;
++
++U_NAMESPACE_END
++
+ typedef enum ELocalePos {
+ eENGLISH,
+ eFRENCH,
+@@ -77,10 +93,6 @@
+ UBool valuesToo,
+ UErrorCode *status);
+
+-static icu::Locale *gLocaleCache = NULL;
+-static icu::Locale *gDefaultLocale = NULL;
+-static UHashtable *gDefaultLocalesHashT = NULL;
+-
+ U_CDECL_BEGIN
+ //
+ // Deleter function for Locales owned by the default Locale hash table/
+@@ -102,24 +114,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
+@@ -127,17 +134,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) {
+@@ -148,100 +148,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;
++ return gDefaultLocale;
+ }
+- 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;
+- }
+- 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 */
+@@ -249,7 +186,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 */
+
+@@ -257,7 +195,6 @@
+ locale_get_default(void)
+ {
+ U_NAMESPACE_USE
+-
+ return Locale::getDefault().getName();
+ }
+
+@@ -663,19 +600,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);
+ }
+
+
+@@ -692,7 +624,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
+diff -ruN icu.orig/source/common/unicode/locid.h icu/source/common/unicode/locid.h
+--- build/icu.orig/source/common/unicode/locid.h 2012-04-05 22:46:08.000000000 +0200
++++ build/icu/source/common/unicode/locid.h 2013-03-05 21:54:11.975608225 +0100
+@@ -738,7 +738,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