Changeset 143400 in webkit


Ignore:
Timestamp:
Feb 19, 2013 4:13:26 PM (11 years ago)
Author:
oliver@apple.com
Message:

Moar hardening
https://bugs.webkit.org/show_bug.cgi?id=110275

Reviewed by Anders Carlsson.

We now poison objects when they get freed, and verify that
any object that is being freed is not poisoned. If the
object looks like it's poisoned we validate the freelist,
and ensure the object is not already present. If it is
we crash.

On allocation, we ensure that the object being allocated
is poisoned, then clear the poisoning fields.

  • wtf/FastMalloc.cpp:

(WTF::internalEntropyValue):
(WTF):
(WTF::freedObjectStartPoison):
(WTF::freedObjectEndPoison):
(TCMalloc_ThreadCache_FreeList):
(WTF::TCMalloc_ThreadCache_FreeList::Validate):
(WTF::TCMalloc_Central_FreeList::Populate):
(WTF::TCMalloc_ThreadCache::Allocate):
(WTF::TCMalloc_ThreadCache::Deallocate):

Location:
trunk/Source/WTF
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r143280 r143400  
     12013-02-19  Oliver Hunt  <oliver@apple.com>
     2
     3        Moar hardening
     4        https://bugs.webkit.org/show_bug.cgi?id=110275
     5
     6        Reviewed by Anders Carlsson.
     7
     8        We now poison objects when they get freed, and verify that
     9        any object that is being freed is not poisoned.  If the
     10        object looks like it's poisoned we validate the freelist,
     11        and ensure the object is not already present.  If it is
     12        we crash.
     13
     14        On allocation, we ensure that the object being allocated
     15        is poisoned, then clear the poisoning fields.
     16
     17        * wtf/FastMalloc.cpp:
     18        (WTF::internalEntropyValue):
     19        (WTF):
     20        (WTF::freedObjectStartPoison):
     21        (WTF::freedObjectEndPoison):
     22        (TCMalloc_ThreadCache_FreeList):
     23        (WTF::TCMalloc_ThreadCache_FreeList::Validate):
     24        (WTF::TCMalloc_Central_FreeList::Populate):
     25        (WTF::TCMalloc_ThreadCache::Allocate):
     26        (WTF::TCMalloc_ThreadCache::Deallocate):
     27
    1282013-02-18  Darin Adler  <darin@apple.com>
    229
  • trunk/Source/WTF/wtf/FastMalloc.cpp

    r142577 r143400  
    545545};
    546546
    547 static ALWAYS_INLINE uintptr_t internalEntropyValue() {
     547static ALWAYS_INLINE uintptr_t internalEntropyValue()
     548{
    548549    static uintptr_t value = EntropySource<sizeof(uintptr_t)>::value();
    549550    ASSERT(value);
     
    555556#define XOR_MASK_PTR_WITH_KEY(ptr, key, entropy) (reinterpret_cast<typeof(ptr)>(reinterpret_cast<uintptr_t>(ptr)^(ROTATE_VALUE(reinterpret_cast<uintptr_t>(key), MaskKeyShift)^entropy)))
    556557
     558
     559static ALWAYS_INLINE uint32_t freedObjectStartPoison()
     560{
     561    static uint32_t value = EntropySource<sizeof(uint32_t)>::value();
     562    ASSERT(value);
     563    return value;
     564}
     565
     566static ALWAYS_INLINE uint32_t freedObjectEndPoison()
     567{
     568    static uint32_t value = EntropySource<sizeof(uint32_t)>::value();
     569    ASSERT(value);
     570    return value;
     571}
     572
     573#define PTR_TO_UINT32(ptr) static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr))
     574#define END_POISON_INDEX(allocationSize) (((allocationSize) - sizeof(uint32_t)) / sizeof(uint32_t))
     575#define POISON_ALLOCATION(allocation, allocationSize) do { \
     576    reinterpret_cast<uint32_t*>(allocation)[0] = 1; \
     577    reinterpret_cast<uint32_t*>(allocation)[1] = 1; \
     578    if (allocationSize < 4 * sizeof(uint32_t)) \
     579        break; \
     580    reinterpret_cast<uint32_t*>(allocation)[2] = 1; \
     581    reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] = 1; \
     582} while (false);
     583
     584#define POISON_DEALLOCATION_EXPLICIT(allocation, allocationSize, startPoison, endPoison) do { \
     585    if (allocationSize < 4 * sizeof(uint32_t)) \
     586        break; \
     587    reinterpret_cast<uint32_t*>(allocation)[2] = (startPoison) ^ PTR_TO_UINT32(allocation); \
     588    reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] = (endPoison) ^ PTR_TO_UINT32(allocation); \
     589} while (false)
     590
     591#define POISON_DEALLOCATION(allocation, allocationSize) \
     592    POISON_DEALLOCATION_EXPLICIT(allocation, allocationSize, freedObjectStartPoison(), freedObjectEndPoison())
     593
     594#define MAY_BE_POISONED(allocation, allocationSize) (((allocationSize) >= 4 * sizeof(uint32_t)) && ( \
     595    (reinterpret_cast<uint32_t*>(allocation)[2] == (freedObjectStartPoison() ^ PTR_TO_UINT32(allocation))) || \
     596    (reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] == (freedObjectEndPoison() ^ PTR_TO_UINT32(allocation))) \
     597))
     598
     599#define IS_DEFINITELY_POISONED(allocation, allocationSize) (((allocationSize) < 4 * sizeof(uint32_t)) || ( \
     600    (reinterpret_cast<uint32_t*>(allocation)[2] == (freedObjectStartPoison() ^ PTR_TO_UINT32(allocation))) && \
     601    (reinterpret_cast<uint32_t*>(allocation)[END_POISON_INDEX(allocationSize)] == (freedObjectEndPoison() ^ PTR_TO_UINT32(allocation))) \
     602))
     603
    557604#else
     605
     606#define POISON_ALLOCATION(allocation, allocationSize)
     607#define POISON_DEALLOCATION(allocation, allocationSize)
     608#define POISON_DEALLOCATION_EXPLICIT(allocation, allocationSize, startPoison, endPoison)
     609#define MAY_BE_POISONED(allocation, allocationSize) (false)
     610#define IS_DEFINITELY_POISONED(allocation, allocationSize) (true)
    558611#define XOR_MASK_PTR_WITH_KEY(ptr, key, entropy) (((void)entropy), ((void)key), ptr)
     612
    559613#define HARDENING_ENTROPY 0
    560 #endif
    561 
     614
     615#endif
    562616
    563617//-------------------------------------------------------------------
     
    25312585  }
    25322586
     2587    // Runs through the linked list to ensure that
     2588    // we can do that, and ensures that 'missing'
     2589    // is not present
     2590    NEVER_INLINE void Validate(HardenedSLL missing) {
     2591        HardenedSLL node = list_;
     2592        while (node) {
     2593            RELEASE_ASSERT(node != missing);
     2594            node = SLL_Next(node, entropy_);
     2595        }
     2596    }
     2597
    25332598#ifdef WTF_CHANGES
    25342599  template <class Finder, class Reader>
     
    30423107  char* ptr = start + (npages << kPageShift) - ((npages << kPageShift) % size);
    30433108  int num = 0;
     3109#if ENABLE(TCMALLOC_HARDENING)
     3110  uint32_t startPoison = freedObjectStartPoison();
     3111  uint32_t endPoison = freedObjectEndPoison();
     3112#endif
     3113
    30443114  while (ptr > start) {
    30453115    ptr -= size;
    30463116    HardenedSLL node = HardenedSLL::create(ptr);
     3117    POISON_DEALLOCATION_EXPLICIT(ptr, size, startPoison, endPoison);
    30473118    SLL_SetNext(node, head, entropy_);
    30483119    head = node;
     
    31163187  }
    31173188  size_ -= allocationSize;
    3118   return list->Pop();
     3189  void* result = list->Pop();
     3190  if (!result)
     3191      return 0;
     3192  RELEASE_ASSERT(IS_DEFINITELY_POISONED(result, allocationSize));
     3193  POISON_ALLOCATION(result, allocationSize);
     3194  return result;
    31193195}
    31203196
    31213197inline void TCMalloc_ThreadCache::Deallocate(HardenedSLL ptr, size_t cl) {
    3122   size_ += ByteSizeForClass(cl);
     3198  size_t allocationSize = ByteSizeForClass(cl);
     3199  size_ += allocationSize;
    31233200  FreeList* list = &list_[cl];
     3201  if (MAY_BE_POISONED(ptr.value(), allocationSize))
     3202      list->Validate(ptr);
     3203
     3204  POISON_DEALLOCATION(ptr.value(), allocationSize);
    31243205  list->Push(ptr);
    31253206  // If enough data is free, put back into central cache
Note: See TracChangeset for help on using the changeset viewer.