forked from mirrors/gecko-dev
Bug 1402282 - Change jemalloc to use secure random private arena ids r=glandium
Previously the id for a new arena was just a counter that increased by one every time. For hardening purposes, we want to make private arenas use a secure random ID, so an attacker will have a more difficult time finding the memory they are looking for. Differential Revision: https://phabricator.services.mozilla.com/D10158 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
29879177ba
commit
adde9e8556
3 changed files with 47 additions and 17 deletions
|
|
@ -132,6 +132,7 @@
|
||||||
#include "mozilla/DoublyLinkedList.h"
|
#include "mozilla/DoublyLinkedList.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
|
#include "mozilla/RandomNum.h"
|
||||||
#include "mozilla/Sprintf.h"
|
#include "mozilla/Sprintf.h"
|
||||||
// Note: MozTaggedAnonymousMmap() could call an LD_PRELOADed mmap
|
// Note: MozTaggedAnonymousMmap() could call an LD_PRELOADed mmap
|
||||||
// instead of the one defined here; use only MozTagAnonymousMemory().
|
// instead of the one defined here; use only MozTagAnonymousMemory().
|
||||||
|
|
@ -1158,8 +1159,10 @@ public:
|
||||||
Mutex mLock;
|
Mutex mLock;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
inline arena_t* GetByIdInternal(arena_id_t aArenaId, bool aIsPrivate);
|
||||||
|
|
||||||
arena_t* mDefaultArena;
|
arena_t* mDefaultArena;
|
||||||
arena_id_t mLastArenaId;
|
arena_id_t mLastPublicArenaId;
|
||||||
Tree mArenas;
|
Tree mArenas;
|
||||||
Tree mPrivateArenas;
|
Tree mPrivateArenas;
|
||||||
};
|
};
|
||||||
|
|
@ -3734,10 +3737,34 @@ ArenaCollection::CreateArena(bool aIsPrivate, arena_params_t* aParams)
|
||||||
|
|
||||||
MutexAutoLock lock(mLock);
|
MutexAutoLock lock(mLock);
|
||||||
|
|
||||||
// TODO: Use random Ids.
|
// For public arenas, it's fine to just use incrementing arena id
|
||||||
ret->mId = mLastArenaId++;
|
if (!aIsPrivate) {
|
||||||
(aIsPrivate ? mPrivateArenas : mArenas).Insert(ret);
|
ret->mId = mLastPublicArenaId++;
|
||||||
return ret;
|
mArenas.Insert(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For private arenas, generate a cryptographically-secure random id for the
|
||||||
|
// new arena. If an attacker manages to get control of the process, this
|
||||||
|
// should make it more difficult for them to "guess" the ID of a memory
|
||||||
|
// arena, stopping them from getting data they may want
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
mozilla::Maybe<uint64_t> maybeRandomId = mozilla::RandomUint64();
|
||||||
|
MOZ_RELEASE_ASSERT(maybeRandomId.isSome());
|
||||||
|
|
||||||
|
// Keep looping until we ensure that the random number we just generated
|
||||||
|
// isn't already in use by another active arena
|
||||||
|
arena_t* existingArena =
|
||||||
|
GetByIdInternal(maybeRandomId.value(), true /*aIsPrivate*/);
|
||||||
|
|
||||||
|
if (!existingArena) {
|
||||||
|
ret->mId = static_cast<arena_id_t>(maybeRandomId.value());
|
||||||
|
mPrivateArenas.Insert(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End arena.
|
// End arena.
|
||||||
|
|
@ -4561,18 +4588,25 @@ MozJemalloc::jemalloc_free_dirty_pages(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline arena_t*
|
||||||
|
ArenaCollection::GetByIdInternal(arena_id_t aArenaId, bool aIsPrivate)
|
||||||
|
{
|
||||||
|
// Use AlignedStorage2 to avoid running the arena_t constructor, while
|
||||||
|
// we only need it as a placeholder for mId.
|
||||||
|
mozilla::AlignedStorage2<arena_t> key;
|
||||||
|
key.addr()->mId = aArenaId;
|
||||||
|
return (aIsPrivate ? mPrivateArenas : mArenas).Search(key.addr());
|
||||||
|
}
|
||||||
|
|
||||||
inline arena_t*
|
inline arena_t*
|
||||||
ArenaCollection::GetById(arena_id_t aArenaId, bool aIsPrivate)
|
ArenaCollection::GetById(arena_id_t aArenaId, bool aIsPrivate)
|
||||||
{
|
{
|
||||||
if (!malloc_initialized) {
|
if (!malloc_initialized) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// Use AlignedStorage2 to avoid running the arena_t constructor, while
|
|
||||||
// we only need it as a placeholder for mId.
|
|
||||||
mozilla::AlignedStorage2<arena_t> key;
|
|
||||||
key.addr()->mId = aArenaId;
|
|
||||||
MutexAutoLock lock(mLock);
|
MutexAutoLock lock(mLock);
|
||||||
arena_t* result = (aIsPrivate ? mPrivateArenas : mArenas).Search(key.addr());
|
arena_t* result = GetByIdInternal(aArenaId, aIsPrivate);
|
||||||
MOZ_RELEASE_ASSERT(result);
|
MOZ_RELEASE_ASSERT(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -300,12 +300,6 @@ MOZ_BEGIN_EXTERN_C
|
||||||
#include "malloc_decls.h"
|
#include "malloc_decls.h"
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
/* mozjemalloc uses MozTagAnonymousMemory, which doesn't have an inline
|
|
||||||
* implementation on Android */
|
|
||||||
void
|
|
||||||
MozTagAnonymousMemory(const void* aPtr, size_t aLength, const char* aTag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mozjemalloc and jemalloc use pthread_atfork, which Android doesn't have.
|
/* mozjemalloc and jemalloc use pthread_atfork, which Android doesn't have.
|
||||||
* While gecko has one in libmozglue, the replay program can't use that.
|
* While gecko has one in libmozglue, the replay program can't use that.
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ Program('logalloc-replay')
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'/mfbt/Assertions.cpp',
|
'/mfbt/Assertions.cpp',
|
||||||
|
'/mfbt/Poison.cpp',
|
||||||
|
'/mfbt/RandomNum.cpp',
|
||||||
|
'/mfbt/TaggedAnonymousMemory.cpp',
|
||||||
'/mfbt/Unused.cpp',
|
'/mfbt/Unused.cpp',
|
||||||
'Replay.cpp',
|
'Replay.cpp',
|
||||||
]
|
]
|
||||||
|
|
@ -16,7 +19,6 @@ if CONFIG['MOZ_REPLACE_MALLOC_STATIC'] and CONFIG['MOZ_DMD']:
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'/mfbt/HashFunctions.cpp',
|
'/mfbt/HashFunctions.cpp',
|
||||||
'/mfbt/JSONWriter.cpp',
|
'/mfbt/JSONWriter.cpp',
|
||||||
'/mfbt/Poison.cpp',
|
|
||||||
'/mozglue/misc/StackWalk.cpp',
|
'/mozglue/misc/StackWalk.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue