Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(575)

Unified Diff: base/process_util_mac.mm

Issue 7670025: [Mac] Implement base::EnableTerminationOnHeapCorruption() by overriding malloc_error_break(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch mach_override Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/process_util_linux.cc ('k') | base/process_util_posix.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/process_util_mac.mm
diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm
index 7db44d900530d7d79150ca819194393bdb961b76..ceb4f0a540073bd0b92ff6ba7b23096258407c0e 100644
--- a/base/process_util_mac.mm
+++ b/base/process_util_mac.mm
@@ -12,6 +12,8 @@
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
#include <mach/task.h>
+#include <mach-o/dyld.h>
+#include <mach-o/nlist.h>
#include <malloc/malloc.h>
#import <objc/runtime.h>
#include <spawn.h>
@@ -34,6 +36,7 @@
#include "base/time.h"
#include "third_party/apple_apsl/CFBase.h"
#include "third_party/apple_apsl/malloc.h"
+#include "third_party/mach_override/mach_override.h"
namespace base {
@@ -483,6 +486,88 @@ size_t GetSystemCommitCharge() {
return (data.active_count * page_size) / 1024;
}
+namespace {
+
+// Finds the library path for malloc() and thus the libC part of libSystem,
+// which in Lion is in a separate image.
+const char* LookUpLibCPath() {
+ const void* addr = reinterpret_cast<void*>(&malloc);
+
+ Dl_info info;
+ if (dladdr(addr, &info))
+ return info.dli_fname;
+
+ LOG(WARNING) << "Could not find image path for malloc()";
+ return NULL;
+}
+
+typedef void(*malloc_error_break_t)(void);
+malloc_error_break_t g_original_malloc_error_break = NULL;
+
+// Returns the function pointer for malloc_error_break. This symbol is declared
+// as __private_extern__ and cannot be dlsym()ed. Instead, use nlist() to
+// get it.
+malloc_error_break_t LookUpMallocErrorBreak() {
Scott Hess - ex-Googler 2011/08/22 19:50:35 Would it be worthwhile to unify this with the comp
Robert Sesek 2011/08/22 19:52:14 We want to explicitly discourage this kind of very
Mark Mentovai 2011/08/22 20:07:23 shess wrote:
+#if ARCH_CPU_32_BITS
+ const char* lib_c_path = LookUpLibCPath();
+ if (!lib_c_path)
+ return NULL;
+
+ // Only need to look up two symbols, but nlist() requires a NULL-terminated
+ // array and takes no count.
+ struct nlist nl[3];
+ bzero(&nl, sizeof(nl));
+
+ // The symbol to find.
+ nl[0].n_un.n_name = const_cast<char*>("_malloc_error_break");
+
+ // A reference symbol by which the address of the desired symbol will be
+ // calculated.
+ nl[1].n_un.n_name = const_cast<char*>("_malloc");
+
+ int rv = nlist(lib_c_path, nl);
+ if (rv != 0 || nl[0].n_type == N_UNDF || nl[1].n_type == N_UNDF) {
+ return NULL;
+ }
+
+ // nlist() returns addresses as offsets in the image, not the instruction
+ // pointer in memory. Use the known in-memory address of malloc()
+ // to compute the offset for malloc_error_break().
+ uintptr_t reference_addr = reinterpret_cast<uintptr_t>(&malloc);
+ reference_addr -= nl[1].n_value;
+ reference_addr += nl[0].n_value;
+
+ return reinterpret_cast<malloc_error_break_t>(reference_addr);
+#endif // ARCH_CPU_32_BITS
+
+ return NULL;
+}
+
+void CrMallocErrorBreak() {
+ g_original_malloc_error_break();
+ LOG(ERROR) <<
+ "Terminating process due to a potential for future heap corruption";
+ base::debug::BreakDebugger();
+}
+
+} // namespace
+
+void EnableTerminationOnHeapCorruption() {
+ malloc_error_break_t malloc_error_break = LookUpMallocErrorBreak();
+ if (!malloc_error_break) {
+ LOG(WARNING) << "Could not find malloc_error_break";
+ return;
+ }
+
+ mach_error_t err = mach_override_ptr(
+ (void*)malloc_error_break,
+ (void*)&CrMallocErrorBreak,
+ (void**)&g_original_malloc_error_break);
+
+ if (err != err_none)
+ LOG(WARNING) << "Could not override malloc_error_break; error = " << err;
+}
+
// ------------------------------------------------------------------------
namespace {
« no previous file with comments | « base/process_util_linux.cc ('k') | base/process_util_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698