diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 21:28:27 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 21:28:27 +0000 |
commit | 78711ce43ea5cefa47f9b066b5cbafeaaf2641cc (patch) | |
tree | 386b9c80891f38b0bfb22f5d97d9cd29b69c4434 /base/process_util_linux.cc | |
parent | 7e08009603d63ce4ff7914a3b984c7b9c99c0556 (diff) | |
download | chromium_src-78711ce43ea5cefa47f9b066b5cbafeaaf2641cc.zip chromium_src-78711ce43ea5cefa47f9b066b5cbafeaaf2641cc.tar.gz chromium_src-78711ce43ea5cefa47f9b066b5cbafeaaf2641cc.tar.bz2 |
Linux: reenable malloc overrides.
(These were disabled in r35804 and r35810.)
This time we are using the __libc_* names to get at the real glibc
functions rather than dlsym. This now means that code that calls
__libc_* gets the raw functions, not 'safe' ones. Also, this sets the
visibility correctly. Previously we were not overriding malloc calls
made in shared libraries.
BUG=31809
TEST=Covered by unittests.
http://codereview.chromium.org/533001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35823 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/process_util_linux.cc')
-rw-r--r-- | base/process_util_linux.cc | 115 |
1 files changed, 49 insertions, 66 deletions
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc index 5d83bd6..a4b2603 100644 --- a/base/process_util_linux.cc +++ b/base/process_util_linux.cc @@ -513,55 +513,60 @@ void OnNoMemory() { } // namespace extern "C" { -// This code tries to make malloc failures fatal for security reasons. However, -// it breaks builds depending on fine details of the linker command line and -// the dependencies of other .so's that we pull in. So it's disabled for the -// moment. See crbug.com/31809 -// -// If enabling this, remember to reanble the tests in process_util_unittest.cc -#if 0 #if !defined(LINUX_USE_TCMALLOC) -typedef void* (*malloc_type)(size_t size); -typedef void* (*valloc_type)(size_t size); -typedef void* (*pvalloc_type)(size_t size); - -typedef void* (*calloc_type)(size_t nmemb, size_t size); -typedef void* (*realloc_type)(void *ptr, size_t size); -typedef void* (*memalign_type)(size_t boundary, size_t size); - -typedef int (*posix_memalign_type)(void **memptr, size_t alignment, - size_t size); +extern "C" { +void* __libc_malloc(size_t size); +void* __libc_realloc(void* ptr, size_t size); +void* __libc_calloc(size_t nmemb, size_t size); +void* __libc_valloc(size_t size); +void* __libc_pvalloc(size_t size); +void* __libc_memalign(size_t alignment, size_t size); +} // extern "C" + +// Overriding the system memory allocation functions: +// +// For security reasons, we want malloc failures to be fatal. Too much code +// doesn't check for a NULL return value from malloc and unconditionally uses +// the resulting pointer. If the first offset that they try to access is +// attacker controlled, then the attacker can direct the code to access any +// part of memory. +// +// Thus, we define all the standard malloc functions here and mark them as +// visibility 'default'. This means that they replace the malloc functions for +// all Chromium code and also for all code in shared libraries. There are tests +// for this in process_util_unittest.cc. +// +// If we are using tcmalloc, then the problem is moot since tcmalloc handles +// this for us. Thus this code is in a !defined(LINUX_USE_TCMALLOC) block. +// +// We call the real libc functions in this code by using __libc_malloc etc. +// Previously we tried using dlsym(RTLD_NEXT, ...) but that failed depending on +// the link order. Since ld.so needs calloc during symbol resolution, it +// defines its own versions of several of these functions in dl-minimal.c. +// Depending on the runtime library order, dlsym ended up giving us those +// functions and bad things happened. See crbug.com/31809 +// +// This means that any code which calls __libc_* gets the raw libc versions of +// these functions. -// Override the __libc_FOO name too. #define DIE_ON_OOM_1(function_name) \ - _DIE_ON_OOM_1(function_name##_type, function_name) \ - void* __libc_##function_name(size_t size) { \ - return function_name(size); \ - } - -#define DIE_ON_OOM_2(function_name, arg1_type) \ - _DIE_ON_OOM_2(function_name##_type, function_name, arg1_type) \ - void* __libc_##function_name(arg1_type arg1, size_t size) { \ - return function_name(arg1, size); \ - } - -#define _DIE_ON_OOM_1(function_type, function_name) \ + void* function_name(size_t) __attribute__ ((visibility("default"))); \ + \ void* function_name(size_t size) { \ - static function_type original_function = \ - reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \ - void* ret = original_function(size); \ + void* ret = __libc_##function_name(size); \ if (ret == NULL && size != 0) \ OnNoMemorySize(size); \ return ret; \ } -#define _DIE_ON_OOM_2(function_type, function_name, arg1_type) \ +#define DIE_ON_OOM_2(function_name, arg1_type) \ + void* function_name(arg1_type, size_t) \ + __attribute__ ((visibility("default"))); \ + \ void* function_name(arg1_type arg1, size_t size) { \ - static function_type original_function = \ - reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \ - void* ret = original_function(arg1, size); \ + void* ret = __libc_##function_name(arg1, size); \ if (ret == NULL && size != 0) \ OnNoMemorySize(size); \ return ret; \ @@ -571,43 +576,21 @@ DIE_ON_OOM_1(malloc) DIE_ON_OOM_1(valloc) DIE_ON_OOM_1(pvalloc) +DIE_ON_OOM_2(calloc, size_t) DIE_ON_OOM_2(realloc, void*) DIE_ON_OOM_2(memalign, size_t) -// dlsym uses calloc so it has to be treated specially. http://crbug.com/28244 -static void* null_calloc(size_t nmemb, size_t size) { - return NULL; -} - -void* calloc(size_t nmemb, size_t size) { - static calloc_type original_function = NULL; - if (original_function == NULL) { - original_function = null_calloc; - original_function = reinterpret_cast<calloc_type>(dlsym(RTLD_NEXT, - "calloc")); - } - void* ret = original_function(nmemb, size); - if (ret == NULL && size != 0 && original_function != null_calloc) - OnNoMemorySize(size); - return ret; -} - -void* __libc_calloc(size_t nmemb, size_t size) { \ - return calloc(nmemb, size); -} - // posix_memalign has a unique signature and doesn't have a __libc_ variant. +int posix_memalign(void** ptr, size_t alignment, size_t size) + __attribute__ ((visibility("default"))); + int posix_memalign(void** ptr, size_t alignment, size_t size) { - static posix_memalign_type original_function = - reinterpret_cast<posix_memalign_type>(dlsym(RTLD_NEXT, "posix_memalign")); - int ret = original_function(ptr, alignment, size); - if (ret == ENOMEM) - OnNoMemorySize(size); - return ret; + // This will use the safe version of memalign, above. + *ptr = memalign(alignment, size); + return 0; } #endif // !defined(LINUX_USE_TCMALLOC) -#endif } // extern C void EnableTerminationOnOutOfMemory() { |