mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
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
@ -132,6 +132,7 @@
|
||||
#include "mozilla/DoublyLinkedList.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/RandomNum.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
// Note: MozTaggedAnonymousMmap() could call an LD_PRELOADed mmap
|
||||
// instead of the one defined here; use only MozTagAnonymousMemory().
|
||||
@ -1158,8 +1159,10 @@ public:
|
||||
Mutex mLock;
|
||||
|
||||
private:
|
||||
inline arena_t* GetByIdInternal(arena_id_t aArenaId, bool aIsPrivate);
|
||||
|
||||
arena_t* mDefaultArena;
|
||||
arena_id_t mLastArenaId;
|
||||
arena_id_t mLastPublicArenaId;
|
||||
Tree mArenas;
|
||||
Tree mPrivateArenas;
|
||||
};
|
||||
@ -3734,10 +3737,34 @@ ArenaCollection::CreateArena(bool aIsPrivate, arena_params_t* aParams)
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
// TODO: Use random Ids.
|
||||
ret->mId = mLastArenaId++;
|
||||
(aIsPrivate ? mPrivateArenas : mArenas).Insert(ret);
|
||||
return ret;
|
||||
// For public arenas, it's fine to just use incrementing arena id
|
||||
if (!aIsPrivate) {
|
||||
ret->mId = mLastPublicArenaId++;
|
||||
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.
|
||||
@ -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*
|
||||
ArenaCollection::GetById(arena_id_t aArenaId, bool aIsPrivate)
|
||||
{
|
||||
if (!malloc_initialized) {
|
||||
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);
|
||||
arena_t* result = (aIsPrivate ? mPrivateArenas : mArenas).Search(key.addr());
|
||||
arena_t* result = GetByIdInternal(aArenaId, aIsPrivate);
|
||||
MOZ_RELEASE_ASSERT(result);
|
||||
return result;
|
||||
}
|
||||
|
@ -300,12 +300,6 @@ MOZ_BEGIN_EXTERN_C
|
||||
#include "malloc_decls.h"
|
||||
|
||||
#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.
|
||||
* While gecko has one in libmozglue, the replay program can't use that.
|
||||
|
@ -8,6 +8,9 @@ Program('logalloc-replay')
|
||||
|
||||
SOURCES += [
|
||||
'/mfbt/Assertions.cpp',
|
||||
'/mfbt/Poison.cpp',
|
||||
'/mfbt/RandomNum.cpp',
|
||||
'/mfbt/TaggedAnonymousMemory.cpp',
|
||||
'/mfbt/Unused.cpp',
|
||||
'Replay.cpp',
|
||||
]
|
||||
@ -16,7 +19,6 @@ if CONFIG['MOZ_REPLACE_MALLOC_STATIC'] and CONFIG['MOZ_DMD']:
|
||||
UNIFIED_SOURCES += [
|
||||
'/mfbt/HashFunctions.cpp',
|
||||
'/mfbt/JSONWriter.cpp',
|
||||
'/mfbt/Poison.cpp',
|
||||
'/mozglue/misc/StackWalk.cpp',
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user