security/sandbox/chromium/base/debug/profiler.cc

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include "base/debug/profiler.h"
     7 #include <string>
     9 #include "base/process/process_handle.h"
    10 #include "base/strings/string_util.h"
    11 #include "base/strings/stringprintf.h"
    13 #if defined(OS_WIN)
    14 #include "base/win/pe_image.h"
    15 #endif  // defined(OS_WIN)
    17 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
    18 #include "third_party/tcmalloc/chromium/src/gperftools/profiler.h"
    19 #endif
    21 namespace base {
    22 namespace debug {
    24 #if defined(ENABLE_PROFILING) && !defined(NO_TCMALLOC)
    26 static int profile_count = 0;
    28 void StartProfiling(const std::string& name) {
    29   ++profile_count;
    30   std::string full_name(name);
    31   std::string pid = StringPrintf("%d", GetCurrentProcId());
    32   std::string count = StringPrintf("%d", profile_count);
    33   ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
    34   ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
    35   ProfilerStart(full_name.c_str());
    36 }
    38 void StopProfiling() {
    39   ProfilerFlush();
    40   ProfilerStop();
    41 }
    43 void FlushProfiling() {
    44   ProfilerFlush();
    45 }
    47 bool BeingProfiled() {
    48   return ProfilingIsEnabledForAllThreads();
    49 }
    51 void RestartProfilingAfterFork() {
    52   ProfilerRegisterThread();
    53 }
    55 #else
    57 void StartProfiling(const std::string& name) {
    58 }
    60 void StopProfiling() {
    61 }
    63 void FlushProfiling() {
    64 }
    66 bool BeingProfiled() {
    67   return false;
    68 }
    70 void RestartProfilingAfterFork() {
    71 }
    73 #endif
    75 #if !defined(OS_WIN)
    77 bool IsBinaryInstrumented() {
    78   return false;
    79 }
    81 ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
    82   return NULL;
    83 }
    85 DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
    86   return NULL;
    87 }
    89 AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
    90   return NULL;
    91 }
    93 MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
    94   return NULL;
    95 }
    97 #else  // defined(OS_WIN)
    99 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
   100 extern "C" IMAGE_DOS_HEADER __ImageBase;
   102 bool IsBinaryInstrumented() {
   103   enum InstrumentationCheckState {
   104     UNINITIALIZED,
   105     INSTRUMENTED_IMAGE,
   106     NON_INSTRUMENTED_IMAGE,
   107   };
   109   static InstrumentationCheckState state = UNINITIALIZED;
   111   if (state == UNINITIALIZED) {
   112     HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
   113     base::win::PEImage image(this_module);
   115     // Check to be sure our image is structured as we'd expect.
   116     DCHECK(image.VerifyMagic());
   118     // Syzygy-instrumented binaries contain a PE image section named ".thunks",
   119     // and all Syzygy-modified binaries contain the ".syzygy" image section.
   120     // This is a very fast check, as it only looks at the image header.
   121     if ((image.GetImageSectionHeaderByName(".thunks") != NULL) &&
   122         (image.GetImageSectionHeaderByName(".syzygy") != NULL)) {
   123       state = INSTRUMENTED_IMAGE;
   124     } else {
   125       state = NON_INSTRUMENTED_IMAGE;
   126     }
   127   }
   128   DCHECK(state != UNINITIALIZED);
   130   return state == INSTRUMENTED_IMAGE;
   131 }
   133 namespace {
   135 struct FunctionSearchContext {
   136   const char* name;
   137   FARPROC function;
   138 };
   140 // Callback function to PEImage::EnumImportChunks.
   141 bool FindResolutionFunctionInImports(
   142     const base::win::PEImage &image, const char* module_name,
   143     PIMAGE_THUNK_DATA unused_name_table, PIMAGE_THUNK_DATA import_address_table,
   144     PVOID cookie) {
   145   FunctionSearchContext* context =
   146       reinterpret_cast<FunctionSearchContext*>(cookie);
   148   DCHECK_NE(static_cast<FunctionSearchContext*>(NULL), context);
   149   DCHECK_EQ(static_cast<FARPROC>(NULL), context->function);
   151   // Our import address table contains pointers to the functions we import
   152   // at this point. Let's retrieve the first such function and use it to
   153   // find the module this import was resolved to by the loader.
   154   const wchar_t* function_in_module =
   155       reinterpret_cast<const wchar_t*>(import_address_table->u1.Function);
   157   // Retrieve the module by a function in the module.
   158   const DWORD kFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
   159                        GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
   160   HMODULE module = NULL;
   161   if (!::GetModuleHandleEx(kFlags, function_in_module, &module)) {
   162     // This can happen if someone IAT patches us to a thunk.
   163     return true;
   164   }
   166   // See whether this module exports the function we're looking for.
   167   FARPROC exported_func = ::GetProcAddress(module, context->name);
   168   if (exported_func != NULL) {
   169     // We found it, return the function and terminate the enumeration.
   170     context->function = exported_func;
   171     return false;
   172   }
   174   // Keep going.
   175   return true;
   176 }
   178 template <typename FunctionType>
   179 FunctionType FindFunctionInImports(const char* function_name) {
   180   if (!IsBinaryInstrumented())
   181     return NULL;
   183   HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
   184   base::win::PEImage image(this_module);
   186   FunctionSearchContext ctx = { function_name, NULL };
   187   image.EnumImportChunks(FindResolutionFunctionInImports, &ctx);
   189   return reinterpret_cast<FunctionType>(ctx.function);
   190 }
   192 }  // namespace
   194 ReturnAddressLocationResolver GetProfilerReturnAddrResolutionFunc() {
   195   return FindFunctionInImports<ReturnAddressLocationResolver>(
   196       "ResolveReturnAddressLocation");
   197 }
   199 DynamicFunctionEntryHook GetProfilerDynamicFunctionEntryHookFunc() {
   200   return FindFunctionInImports<DynamicFunctionEntryHook>(
   201       "OnDynamicFunctionEntry");
   202 }
   204 AddDynamicSymbol GetProfilerAddDynamicSymbolFunc() {
   205   return FindFunctionInImports<AddDynamicSymbol>(
   206       "AddDynamicSymbol");
   207 }
   209 MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() {
   210   return FindFunctionInImports<MoveDynamicSymbol>(
   211       "MoveDynamicSymbol");
   212 }
   214 #endif  // defined(OS_WIN)
   216 }  // namespace debug
   217 }  // namespace base

mercurial