mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Backed out 6 changesets (bug 1917575, bug 1917844, bug 1874689, bug 1918596, bug 1915152) for causing ContentChild crashes. CLOSED TREE
Backed out changeset d6dc6d8085b5 (bug 1874689) Backed out changeset 8c3916995be2 (bug 1918596) Backed out changeset f77e369d1e0f (bug 1917844) Backed out changeset 3bee9479316a (bug 1917844) Backed out changeset 5c72e4a84a2c (bug 1917575) Backed out changeset af3350e58b0a (bug 1915152)
This commit is contained in:
parent
a1d100d7d1
commit
1bc4690f6a
@ -804,13 +804,6 @@ void ContentChild::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
|
||||
PendingInputEventHangAnnotator::sSingleton);
|
||||
}));
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_MEMORY) && defined(DEBUG)
|
||||
jemalloc_stats_t stats;
|
||||
jemalloc_stats(&stats);
|
||||
MOZ_ASSERT(!stats.opt_randomize_small,
|
||||
"Content process should not randomize small allocations");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ContentChild::AddProfileToProcessName(const nsACString& aProfile) {
|
||||
|
@ -144,45 +144,6 @@ void setproctitle(const char* fmt, ...) {
|
||||
if (!buggy_kernel && size < argv_size) {
|
||||
g_argv_end[-1] = '.';
|
||||
}
|
||||
|
||||
const size_t previous_size = g_argv_end - g_argv_start - 1;
|
||||
ssize_t need_to_save = static_cast<ssize_t>(size - previous_size);
|
||||
|
||||
// The argv part has grown so there is less room for the environ part.
|
||||
// Selectively removing a few environment variables so this can fit.
|
||||
//
|
||||
// The goal is trying to make sure that the environment in the
|
||||
// /proc/PID/environ content for crashes is useful
|
||||
const char* kEnvSkip[] = {"HOME=", "LS_COLORS=", "PATH=", "XDG_DATA_DIRS="};
|
||||
const size_t kEnvElems = sizeof(kEnvSkip) / sizeof(kEnvSkip[0]);
|
||||
|
||||
size_t environ_size = 0;
|
||||
for (size_t i = 0; environ[i]; ++i) {
|
||||
bool skip = false;
|
||||
const size_t var_size = strlen(environ[i]) + 1;
|
||||
|
||||
for (size_t remI = 0; need_to_save > 0 && remI < kEnvElems; ++remI) {
|
||||
const char* thisEnv = kEnvSkip[remI];
|
||||
size_t thisEnvSize = sizeof(kEnvSkip[remI]);
|
||||
int diff = strncmp(environ[i], thisEnv, thisEnvSize);
|
||||
if (diff == 0) {
|
||||
need_to_save -= static_cast<ssize_t>(var_size);
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char* env_start = g_argv_end + environ_size;
|
||||
if ((env_start + var_size) < g_envp_end) {
|
||||
const size_t var_size_copied =
|
||||
snprintf(env_start, var_size, "%s", environ[i]);
|
||||
environ_size += var_size_copied + 1 /* account for null */;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A version of this built into glibc would not need this function, since
|
||||
|
@ -205,13 +205,6 @@ bool ForkServer::OnMessageReceived(UniquePtr<IPC::Message> message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_MEMORY) && defined(DEBUG)
|
||||
jemalloc_stats_t stats;
|
||||
jemalloc_stats(&stats);
|
||||
MOZ_ASSERT(stats.narenas == 1,
|
||||
"ForkServer before fork()/clone() should have a single arena.");
|
||||
#endif
|
||||
|
||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
mozilla::SandboxLaunch launcher;
|
||||
if (!launcher.Prepare(&options)) {
|
||||
@ -325,17 +318,6 @@ bool ForkServer::RunForkServer(int* aArgc, char*** aArgv) {
|
||||
MOZ_ASSERT(!XRE_IsForkServerProcess(),
|
||||
"fork server created another fork server?");
|
||||
|
||||
// This is now a child process, and it may even be a Content process.
|
||||
// It is required that the PRNG at least is re-initialized so the same state
|
||||
// is not shared accross all child processes, and in case of a Content process
|
||||
// it is also required that the small allocation are not being randomized ;
|
||||
// failing to do so will lead to performance regressions, e.g. as in
|
||||
// bug 1912262.
|
||||
#if defined(MOZ_MEMORY)
|
||||
jemalloc_reset_small_alloc_randomization(
|
||||
/* aRandomizeSmall */ !XRE_IsContentProcess());
|
||||
#endif
|
||||
|
||||
// Open log files again with right names and the new PID.
|
||||
nsTraceRefcnt::ReopenLogFilesAfterFork(XRE_GetProcessTypeString());
|
||||
|
||||
|
@ -138,13 +138,6 @@ bool UtilityProcessImpl::Init(int aArgc, char* aArgv[]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_MEMORY) && defined(DEBUG)
|
||||
jemalloc_stats_t stats;
|
||||
jemalloc_stats(&stats);
|
||||
MOZ_ASSERT(stats.opt_randomize_small,
|
||||
"Utility process should randomize small allocations");
|
||||
#endif
|
||||
|
||||
return mUtility->Init(TakeInitialEndpoint(), nsCString(*parentBuildID),
|
||||
*sandboxingKind);
|
||||
}
|
||||
|
@ -114,13 +114,6 @@ MALLOC_DECL(jemalloc_free_dirty_pages, void)
|
||||
// after lowering the max dirty pages threshold to get RSS back to normal.
|
||||
MALLOC_DECL(jemalloc_free_excess_dirty_pages, void)
|
||||
|
||||
// Only used by ForkServer after forking new child processes.
|
||||
// Change the value of opt_randomize_small to control small allocation
|
||||
// randomization and maybe perform a reinitialization of the arena's PRNG.
|
||||
# if defined(MOZ_ENABLE_FORKSERVER)
|
||||
MALLOC_DECL(jemalloc_reset_small_alloc_randomization, void, bool)
|
||||
# endif
|
||||
|
||||
// Opt in or out of a thread local arena (bool argument is whether to opt-in
|
||||
// (true) or out (false)).
|
||||
MALLOC_DECL(jemalloc_thread_local_arena, void, bool)
|
||||
|
@ -1204,10 +1204,6 @@ struct arena_t {
|
||||
explicit arena_t(arena_params_t* aParams, bool aIsPrivate);
|
||||
~arena_t();
|
||||
|
||||
void ResetSmallAllocRandomization();
|
||||
|
||||
void InitPRNG() MOZ_REQUIRES(mLock);
|
||||
|
||||
private:
|
||||
void InitChunk(arena_chunk_t* aChunk, size_t aMinCommittedPages);
|
||||
|
||||
@ -3395,40 +3391,6 @@ void arena_bin_t::Init(SizeClass aSizeClass) {
|
||||
mSizeDivisor = FastDivisor<uint16_t>(aSizeClass.Size(), try_run_size);
|
||||
}
|
||||
|
||||
void arena_t::ResetSmallAllocRandomization() {
|
||||
if (MOZ_UNLIKELY(opt_randomize_small)) {
|
||||
MaybeMutexAutoLock lock(mLock);
|
||||
InitPRNG();
|
||||
}
|
||||
mRandomizeSmallAllocations = opt_randomize_small;
|
||||
}
|
||||
|
||||
void arena_t::InitPRNG() {
|
||||
// Both another thread could race and the code backing RandomUint64
|
||||
// (arc4random for example) may allocate memory while here, so we must
|
||||
// ensure to start the mPRNG initialization only once and to not hold
|
||||
// the lock while initializing.
|
||||
mIsPRNGInitializing = true;
|
||||
{
|
||||
mLock.Unlock();
|
||||
mozilla::Maybe<uint64_t> prngState1 = mozilla::RandomUint64();
|
||||
mozilla::Maybe<uint64_t> prngState2 = mozilla::RandomUint64();
|
||||
mLock.Lock();
|
||||
|
||||
mozilla::non_crypto::XorShift128PlusRNG prng(prngState1.valueOr(0),
|
||||
prngState2.valueOr(0));
|
||||
if (mPRNG) {
|
||||
*mPRNG = prng;
|
||||
} else {
|
||||
void* backing =
|
||||
base_alloc(sizeof(mozilla::non_crypto::XorShift128PlusRNG));
|
||||
mPRNG = new (backing)
|
||||
mozilla::non_crypto::XorShift128PlusRNG(std::move(prng));
|
||||
}
|
||||
}
|
||||
mIsPRNGInitializing = false;
|
||||
}
|
||||
|
||||
void* arena_t::MallocSmall(size_t aSize, bool aZero) {
|
||||
void* ret;
|
||||
arena_bin_t* bin;
|
||||
@ -3467,7 +3429,25 @@ void* arena_t::MallocSmall(size_t aSize, bool aZero) {
|
||||
|
||||
if (MOZ_UNLIKELY(mRandomizeSmallAllocations && mPRNG == nullptr &&
|
||||
!mIsPRNGInitializing)) {
|
||||
InitPRNG();
|
||||
// Both another thread could race and the code backing RandomUint64
|
||||
// (arc4random for example) may allocate memory while here, so we must
|
||||
// ensure to start the mPRNG initialization only once and to not hold
|
||||
// the lock while initializing.
|
||||
mIsPRNGInitializing = true;
|
||||
mozilla::non_crypto::XorShift128PlusRNG* prng;
|
||||
{
|
||||
// TODO: I think no MaybeMutexAutoUnlock or similar exists, should it?
|
||||
mLock.Unlock();
|
||||
mozilla::Maybe<uint64_t> prngState1 = mozilla::RandomUint64();
|
||||
mozilla::Maybe<uint64_t> prngState2 = mozilla::RandomUint64();
|
||||
void* backing =
|
||||
base_alloc(sizeof(mozilla::non_crypto::XorShift128PlusRNG));
|
||||
prng = new (backing) mozilla::non_crypto::XorShift128PlusRNG(
|
||||
prngState1.valueOr(0), prngState2.valueOr(0));
|
||||
mLock.Lock();
|
||||
}
|
||||
mPRNG = prng;
|
||||
mIsPRNGInitializing = false;
|
||||
}
|
||||
MOZ_ASSERT(!mRandomizeSmallAllocations || mPRNG);
|
||||
|
||||
@ -4898,7 +4878,6 @@ inline void MozJemalloc::jemalloc_stats_internal(
|
||||
|
||||
// Gather runtime settings.
|
||||
aStats->opt_junk = opt_junk;
|
||||
aStats->opt_randomize_small = opt_randomize_small;
|
||||
aStats->opt_zero = opt_zero;
|
||||
aStats->quantum = kQuantum;
|
||||
aStats->quantum_max = kMaxQuantumClass;
|
||||
@ -5188,39 +5167,6 @@ inline void MozJemalloc::moz_set_max_dirty_page_modifier(int32_t aModifier) {
|
||||
gArenas.SetDefaultMaxDirtyPageModifier(aModifier);
|
||||
}
|
||||
|
||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||
inline void MozJemalloc::jemalloc_reset_small_alloc_randomization(
|
||||
bool aRandomizeSmall) {
|
||||
// When this process got forked by ForkServer then it inherited the existing
|
||||
// state of mozjemalloc. Specifically, parsing of MALLOC_OPTIONS has already
|
||||
// been done but it may not reflect anymore the current set of options after
|
||||
// the fork().
|
||||
//
|
||||
// Content process will have randomization on small malloc disabled via the
|
||||
// MALLOC_OPTIONS environment variable set by parent process, missing this
|
||||
// will lead to serious performance regressions because CPU prefetch will
|
||||
// break, cf bug 1912262. However on forkserver-forked Content processes, the
|
||||
// environment is not yet reset when the postfork child handler is being
|
||||
// called.
|
||||
//
|
||||
// This API is here to allow those forkserver-forked Content processes to
|
||||
// notify jemalloc to turn off the randomization on small allocations and
|
||||
// perform the required reinitialization of already existing arena's PRNG.
|
||||
// It is important to make sure that the PRNG state is properly re-initialized
|
||||
// otherwise child processes would share all the same state.
|
||||
|
||||
{
|
||||
AutoLock<StaticMutex> lock(gInitLock);
|
||||
opt_randomize_small = aRandomizeSmall;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(gArenas.mLock);
|
||||
for (auto* arena : gArenas.iter()) {
|
||||
arena->ResetSmallAllocRandomization();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
inline return_type MozJemalloc::moz_arena_##name( \
|
||||
arena_id_t aArenaId, ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) { \
|
||||
|
@ -96,19 +96,18 @@ typedef struct arena_params_s {
|
||||
// file.
|
||||
typedef struct {
|
||||
// Run-time configuration settings.
|
||||
bool opt_junk; // Fill allocated memory with kAllocJunk?
|
||||
bool opt_randomize_small; // Randomization of small allocations?
|
||||
bool opt_zero; // Fill allocated memory with 0x0?
|
||||
size_t narenas; // Number of arenas.
|
||||
size_t quantum; // Allocation quantum.
|
||||
size_t quantum_max; // Max quantum-spaced allocation size.
|
||||
size_t quantum_wide; // Allocation quantum (QuantuWide).
|
||||
size_t quantum_wide_max; // Max quantum-wide-spaced allocation size.
|
||||
size_t subpage_max; // Max subpage allocation size.
|
||||
size_t large_max; // Max sub-chunksize allocation size.
|
||||
size_t chunksize; // Size of each virtual memory mapping.
|
||||
size_t page_size; // Size of pages.
|
||||
size_t dirty_max; // Max dirty pages per arena.
|
||||
bool opt_junk; // Fill allocated memory with kAllocJunk?
|
||||
bool opt_zero; // Fill allocated memory with 0x0?
|
||||
size_t narenas; // Number of arenas.
|
||||
size_t quantum; // Allocation quantum.
|
||||
size_t quantum_max; // Max quantum-spaced allocation size.
|
||||
size_t quantum_wide; // Allocation quantum (QuantuWide).
|
||||
size_t quantum_wide_max; // Max quantum-wide-spaced allocation size.
|
||||
size_t subpage_max; // Max subpage allocation size.
|
||||
size_t large_max; // Max sub-chunksize allocation size.
|
||||
size_t chunksize; // Size of each virtual memory mapping.
|
||||
size_t page_size; // Size of pages.
|
||||
size_t dirty_max; // Max dirty pages per arena.
|
||||
|
||||
// Current memory usage statistics.
|
||||
size_t mapped; // Bytes mapped (not necessarily committed).
|
||||
|
@ -2985,7 +2985,7 @@
|
||||
#if defined(MOZ_CODE_COVERAGE) || defined(MOZ_ASAN) || defined(MOZ_TSAN) || defined(MOZ_MSAN) || defined(MOZ_UBSAN) || defined(MOZ_PROFILE_GENERATE)
|
||||
value: false
|
||||
#else
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
value: false
|
||||
#endif
|
||||
mirror: once
|
||||
#endif
|
||||
|
@ -17,15 +17,6 @@ if CONFIG["MOZ_CRASHREPORTER"]:
|
||||
"pthread_create_interposer.cpp",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_SANDBOX"]:
|
||||
EXPORTS.mozilla += [
|
||||
"pthread_atfork.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"pthread_atfork_interposer.cpp",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_LINKER"]:
|
||||
LOCAL_INCLUDES += [
|
||||
"/mozglue/linker",
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef __mozilla_pthread_atfork_h_
|
||||
#define __mozilla_pthread_atfork_h_
|
||||
|
||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||
|
||||
# if defined(__GLIBC__) && !defined(__UCLIBC__)
|
||||
// We really are using glibc, not uClibc pretending to be glibc.
|
||||
# define LIBC_GLIBC 1
|
||||
# endif
|
||||
|
||||
extern MFBT_API void run_moz_pthread_atfork_handlers_prefork();
|
||||
extern MFBT_API void run_moz_pthread_atfork_handlers_postfork_parent();
|
||||
extern MFBT_API void run_moz_pthread_atfork_handlers_postfork_child();
|
||||
|
||||
#endif // defined(MOZ_ENABLE_FORKSERVER)
|
||||
#endif // __mozilla_pthread_atfork_h_
|
@ -1,254 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <atomic>
|
||||
#include <array>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "InterposerHelper.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
#if defined(MOZ_ENABLE_FORKSERVER) && !defined(MOZ_TSAN)
|
||||
# include "mozilla/pthread_atfork.h"
|
||||
|
||||
static constexpr const int maxHandlers = 16;
|
||||
static constexpr const int idxPreFork = 0;
|
||||
static constexpr const int idxPostForkParent = 1;
|
||||
static constexpr const int idxPostForkChild = 2;
|
||||
|
||||
struct moz_pthread_atfork_handler {
|
||||
using fn_ptr = std::atomic<void (*)(void)>;
|
||||
using dso_handle = std::atomic<void*>;
|
||||
using pthread_handlers = std::array<fn_ptr, 3>;
|
||||
|
||||
std::atomic<int> usedElems = 0;
|
||||
std::array<pthread_handlers, maxHandlers> handlers = {};
|
||||
std::array<dso_handle, maxHandlers> dsos = {};
|
||||
|
||||
bool add(void (*aPrefork)(void), void (*aParent)(void), void (*aChild)(void),
|
||||
const void* const aHandle) {
|
||||
if (usedElems == maxHandlers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int elem = 0;
|
||||
for (elem = 0; elem < maxHandlers; ++elem) {
|
||||
if (dsos[elem] == nullptr) {
|
||||
handlers[elem][idxPreFork] = aPrefork;
|
||||
handlers[elem][idxPostForkParent] = aParent;
|
||||
handlers[elem][idxPostForkChild] = aChild;
|
||||
dsos[elem] = (void*)(aHandle);
|
||||
++usedElems;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool remove(void* aHandle) {
|
||||
int elem = 0;
|
||||
for (elem = 0; elem < maxHandlers; ++elem) {
|
||||
if (dsos[elem] == aHandle) {
|
||||
handlers[elem][idxPreFork] = nullptr;
|
||||
handlers[elem][idxPostForkParent] = nullptr;
|
||||
handlers[elem][idxPostForkChild] = nullptr;
|
||||
dsos[elem] = nullptr;
|
||||
--usedElems;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct moz_pthread_atfork_handler mozPthreadHandlers;
|
||||
|
||||
# if defined(LIBC_GLIBC)
|
||||
// On glibc the pthread_atfork may be available only from libc_nonshared.a
|
||||
// so prefer interposing the linker-resolved __register_atfork()
|
||||
|
||||
extern const void* const __dso_handle;
|
||||
using register_atfork_t = int (*)(void (*)(), void (*)(), void (*)(),
|
||||
const void* const) noexcept;
|
||||
static register_atfork_t real_register_atfork = nullptr;
|
||||
|
||||
using cxa_finalize_t = void (*)(void*) noexcept;
|
||||
static cxa_finalize_t real_cxa_finalize = nullptr;
|
||||
# else
|
||||
using pthread_atfork_t = int (*)(void (*)(), void (*)(), void (*)()) noexcept;
|
||||
static pthread_atfork_t real_pthread_atfork = nullptr;
|
||||
# endif
|
||||
|
||||
static int notReadyCount = 0;
|
||||
|
||||
extern "C" {
|
||||
|
||||
# if defined(LIBC_GLIBC)
|
||||
MFBT_API int __register_atfork(void (*aPrefork)(void),
|
||||
void (*aPostForkParent)(void),
|
||||
void (*aPostForkChild)(void),
|
||||
const void* const dso_handle)
|
||||
# else
|
||||
MFBT_API int pthread_atfork(void (*aPrefork)(void),
|
||||
void (*aPostForkParent)(void),
|
||||
void (*aPostForkChild)(void))
|
||||
# endif
|
||||
{
|
||||
# if defined(LIBC_GLIBC)
|
||||
MOZ_ASSERT(real_register_atfork != __register_atfork,
|
||||
"Found __register_atfork from libc");
|
||||
# else
|
||||
MOZ_ASSERT(real_pthread_atfork != pthread_atfork,
|
||||
"Found pthread_atfork from libc");
|
||||
# endif
|
||||
|
||||
int rv = 0;
|
||||
# if defined(LIBC_GLIBC)
|
||||
if (real_register_atfork) {
|
||||
real_register_atfork(aPrefork, aPostForkParent, aPostForkChild, dso_handle);
|
||||
# else
|
||||
if (real_pthread_atfork) {
|
||||
real_pthread_atfork(aPrefork, aPostForkParent, aPostForkChild);
|
||||
# endif
|
||||
MOZ_ASSERT(rv == 0, "call to real_register_atfork() failed");
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
++notReadyCount;
|
||||
}
|
||||
|
||||
rv = mozPthreadHandlers.add(aPrefork, aPostForkParent, aPostForkChild
|
||||
# if defined(LIBC_GLIBC)
|
||||
,
|
||||
dso_handle
|
||||
# endif
|
||||
)
|
||||
? 0
|
||||
: 1;
|
||||
MOZ_ASSERT(rv == 0,
|
||||
# if defined(LIBC_GLIBC)
|
||||
"Should have been able to add to __register_atfork() handlers"
|
||||
# else
|
||||
"Should have been able to add to pthread_atfork() handlers"
|
||||
# endif
|
||||
);
|
||||
|
||||
if (rv > 0) {
|
||||
rv = ENOMEM;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
# if defined(LIBC_GLIBC)
|
||||
MFBT_API void __cxa_finalize(void* handle) {
|
||||
real_cxa_finalize(handle);
|
||||
mozPthreadHandlers.remove(handle);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
# if defined(LIBC_GLIBC)
|
||||
__attribute__((used)) __attribute__((constructor)) void register_atfork_setup(
|
||||
void) {
|
||||
const char* glibc_version_register =
|
||||
# if defined(__x86_64__) || defined(__i386__)
|
||||
"GLIBC_2.3.2"
|
||||
# elif defined(__aarch64__)
|
||||
"GLIBC_2.17"
|
||||
# else
|
||||
# error \
|
||||
"Missing GLIBC version for __register_atfork(). Please objdump -tTC libc.so.6 and add"
|
||||
# endif
|
||||
;
|
||||
|
||||
// Use dlvsym() otherwise symbol resolution may find the interposed version
|
||||
real_register_atfork = (register_atfork_t)dlvsym(nullptr, "__register_atfork",
|
||||
glibc_version_register);
|
||||
|
||||
MOZ_ASSERT(real_register_atfork != nullptr, "Found real_register_atfork");
|
||||
MOZ_ASSERT(real_register_atfork != __register_atfork,
|
||||
"Found register_atfork from libc");
|
||||
|
||||
const char* glibc_version_finalize =
|
||||
# if defined(__i386__)
|
||||
"GLIBC_2.1.3"
|
||||
# elif defined(__x86_64__)
|
||||
"GLIBC_2.2.5"
|
||||
# elif defined(__aarch64__)
|
||||
"GLIBC_2.17"
|
||||
# else
|
||||
# error \
|
||||
"Missing GLIBC version for __cxa_finalize(). Please objdump -tTC libc.so.6 and add"
|
||||
# endif
|
||||
;
|
||||
// Use dlvsym() otherwise symbol resolution may find the interposed version
|
||||
real_cxa_finalize =
|
||||
(cxa_finalize_t)dlvsym(nullptr, "__cxa_finalize", glibc_version_finalize);
|
||||
|
||||
MOZ_ASSERT(real_cxa_finalize != nullptr, "Found real_cxa_finalize");
|
||||
MOZ_ASSERT(real_cxa_finalize != __cxa_finalize,
|
||||
"Found cxa_finalize from libc");
|
||||
|
||||
if (notReadyCount > 0) {
|
||||
for (int i = 0; i < notReadyCount; ++i) {
|
||||
real_register_atfork(mozPthreadHandlers.handlers[i][idxPreFork],
|
||||
mozPthreadHandlers.handlers[i][idxPostForkParent],
|
||||
mozPthreadHandlers.handlers[i][idxPostForkChild],
|
||||
__dso_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
# else
|
||||
__attribute__((used)) __attribute__((constructor)) void pthread_atfork_setup(
|
||||
void) {
|
||||
real_pthread_atfork = (pthread_atfork_t)dlsym(RTLD_NEXT, "pthread_atfork");
|
||||
|
||||
MOZ_ASSERT(real_pthread_atfork != nullptr, "Found real_pthread_atfork");
|
||||
MOZ_ASSERT(real_pthread_atfork != pthread_atfork,
|
||||
"Found pthread_atfork from libc");
|
||||
|
||||
if (notReadyCount > 0) {
|
||||
for (int i = 0; i < notReadyCount; ++i) {
|
||||
real_pthread_atfork(mozPthreadHandlers.handlers[i][idxPreFork],
|
||||
mozPthreadHandlers.handlers[i][idxPostForkParent],
|
||||
mozPthreadHandlers.handlers[i][idxPostForkChild]);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
void run_moz_pthread_atfork_handlers(struct moz_pthread_atfork_handler* list,
|
||||
int handlerIdx, bool reverse) {
|
||||
MOZ_ASSERT(list, "moz_pthread_atfork_handler should not be nullptr");
|
||||
for (int i = (reverse ? maxHandlers - 1 : 0);
|
||||
(reverse ? (i >= 0) : (i < maxHandlers)); (reverse ? --i : ++i)) {
|
||||
if (list->dsos[i]) {
|
||||
if (list->handlers[i][handlerIdx]) {
|
||||
(*list->handlers[i][handlerIdx])();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run_moz_pthread_atfork_handlers_prefork() {
|
||||
run_moz_pthread_atfork_handlers(&mozPthreadHandlers, idxPreFork, true);
|
||||
}
|
||||
|
||||
void run_moz_pthread_atfork_handlers_postfork_parent() {
|
||||
run_moz_pthread_atfork_handlers(&mozPthreadHandlers, idxPostForkParent,
|
||||
false);
|
||||
}
|
||||
|
||||
void run_moz_pthread_atfork_handlers_postfork_child() {
|
||||
run_moz_pthread_atfork_handlers(&mozPthreadHandlers, idxPostForkChild, false);
|
||||
}
|
||||
#endif // defined(MOZ_ENABLE_FORKSERVER)
|
@ -45,8 +45,6 @@
|
||||
#include "sandbox/linux/system_headers/linux_syscalls.h"
|
||||
#include "sandbox/linux/services/syscall_wrappers.h"
|
||||
|
||||
#include "mozilla/pthread_atfork.h"
|
||||
|
||||
#ifdef MOZ_X11
|
||||
# ifndef MOZ_WIDGET_GTK
|
||||
# error "Unknown toolkit"
|
||||
@ -625,14 +623,11 @@ pid_t SandboxLaunch::Fork() {
|
||||
// can't run atfork hooks.)
|
||||
sigset_t oldSigs;
|
||||
BlockAllSignals(&oldSigs);
|
||||
run_moz_pthread_atfork_handlers_prefork();
|
||||
pid_t pid = ForkWithFlags(mFlags);
|
||||
if (pid != 0) {
|
||||
run_moz_pthread_atfork_handlers_postfork_parent();
|
||||
RestoreSignals(&oldSigs);
|
||||
return pid;
|
||||
}
|
||||
run_moz_pthread_atfork_handlers_postfork_child();
|
||||
|
||||
// WARNING: all code from this point on (and in StartChrootServer)
|
||||
// must be async signal safe. In particular, it cannot do anything
|
||||
|
Loading…
Reference in New Issue
Block a user