Home | History | Annotate | Download | only in process
      1 // Copyright (c) 2013 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.
      4 
      5 #include "base/process/memory.h"
      6 
      7 #include <psapi.h>
      8 
      9 #include "base/logging.h"
     10 #include "base/memory/scoped_ptr.h"
     11 
     12 namespace base {
     13 
     14 namespace {
     15 
     16 void OnNoMemory() {
     17   // Kill the process. This is important for security, since WebKit doesn't
     18   // NULL-check many memory allocations. If a malloc fails, returns NULL, and
     19   // the buffer is then used, it provides a handy mapping of memory starting at
     20   // address 0 for an attacker to utilize.
     21   __debugbreak();
     22   _exit(1);
     23 }
     24 
     25 // HeapSetInformation function pointer.
     26 typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
     27 
     28 }  // namespace
     29 
     30 bool EnableLowFragmentationHeap() {
     31   HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
     32   HeapSetFn heap_set = reinterpret_cast<HeapSetFn>(GetProcAddress(
     33       kernel32,
     34       "HeapSetInformation"));
     35 
     36   // On Windows 2000, the function is not exported. This is not a reason to
     37   // fail.
     38   if (!heap_set)
     39     return true;
     40 
     41   unsigned number_heaps = GetProcessHeaps(0, NULL);
     42   if (!number_heaps)
     43     return false;
     44 
     45   // Gives us some extra space in the array in case a thread is creating heaps
     46   // at the same time we're querying them.
     47   static const int MARGIN = 8;
     48   scoped_ptr<HANDLE[]> heaps(new HANDLE[number_heaps + MARGIN]);
     49   number_heaps = GetProcessHeaps(number_heaps + MARGIN, heaps.get());
     50   if (!number_heaps)
     51     return false;
     52 
     53   for (unsigned i = 0; i < number_heaps; ++i) {
     54     ULONG lfh_flag = 2;
     55     // Don't bother with the result code. It may fails on heaps that have the
     56     // HEAP_NO_SERIALIZE flag. This is expected and not a problem at all.
     57     heap_set(heaps[i],
     58              HeapCompatibilityInformation,
     59              &lfh_flag,
     60              sizeof(lfh_flag));
     61   }
     62   return true;
     63 }
     64 
     65 void EnableTerminationOnHeapCorruption() {
     66   // Ignore the result code. Supported on XP SP3 and Vista.
     67   HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
     68 }
     69 
     70 void EnableTerminationOnOutOfMemory() {
     71   std::set_new_handler(&OnNoMemory);
     72 }
     73 
     74 HMODULE GetModuleFromAddress(void* address) {
     75   HMODULE instance = NULL;
     76   if (!::GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
     77                             GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
     78                             static_cast<char*>(address),
     79                             &instance)) {
     80     NOTREACHED();
     81   }
     82   return instance;
     83 }
     84 
     85 // TODO(b.kelemen): implement it with the required semantics. On Linux this is
     86 // implemented with a weak symbol that is overridden by tcmalloc. This is
     87 // neccessary because base cannot have a direct dependency on tcmalloc. Since
     88 // weak symbols are not supported on Windows this will involve some build time
     89 // magic, much like what is done for libcrt in order to override the allocation
     90 // functions.
     91 bool UncheckedMalloc(size_t size, void** result) {
     92   *result = malloc(size);
     93   return *result != NULL;
     94 }
     95 
     96 }  // namespace base
     97