summaryrefslogtreecommitdiffstats
path: root/base/process_util_linux.cc
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 21:28:27 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 21:28:27 +0000
commit78711ce43ea5cefa47f9b066b5cbafeaaf2641cc (patch)
tree386b9c80891f38b0bfb22f5d97d9cd29b69c4434 /base/process_util_linux.cc
parent7e08009603d63ce4ff7914a3b984c7b9c99c0556 (diff)
downloadchromium_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.cc115
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() {