| Index: base/process_util_linux.cc
|
| diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
|
| index 5d83bd6c6d6203b0175ce4de18b50b18117a766a..a4b2603c6910fb1dea57fc60c980dd97ec829c48 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() {
|
|
|