# HG changeset patch # User Gian-Carlo Pascutto # Date 1628058287 0 # Node ID 7f9b9624c400dc847dc0053ebe35fbe63353a3d2 # Parent 958aef401f3c27231c426fc6e00024b0741470a6 Bug 1721326 - Allow dynamic PTHREAD_STACK_MIN. r=glandium, a=RyanVM https://phabricator.services.mozilla.com/D120708 Differential Revision: https://phabricator.services.mozilla.com/D120972 diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -81,23 +81,20 @@ # include # include #endif using namespace mozilla; using namespace xpc; using namespace JS; -// The watchdog thread loop is pretty trivial, and should not require much stack -// space to do its job. So only give it 32KiB or the platform minimum. +// We will clamp to reasonable values if this isn't set. #if !defined(PTHREAD_STACK_MIN) # define PTHREAD_STACK_MIN 0 #endif -static constexpr size_t kWatchdogStackSize = - PTHREAD_STACK_MIN < 32 * 1024 ? 32 * 1024 : PTHREAD_STACK_MIN; static void WatchdogMain(void* arg); class Watchdog; class WatchdogManager; class MOZ_RAII AutoLockWatchdog final { Watchdog* const mWatchdog; public: @@ -154,22 +151,29 @@ class Watchdog { // extra pages if we can avoid it. nsCOMPtr dbg = do_GetService("@mozilla.org/xpcom/debug;1"); Unused << dbg; } { AutoLockWatchdog lock(this); + // The watchdog thread loop is pretty trivial, and should not + // require much stack space to do its job. So only give it 32KiB + // or the platform minimum. On modern Linux libc this might resolve to + // a runtime call. + size_t watchdogStackSize = PTHREAD_STACK_MIN; + watchdogStackSize = std::max(32 * 1024, watchdogStackSize); + // Gecko uses thread private for accounting and has to clean up at thread // exit. Therefore, even though we don't have a return value from the // watchdog, we need to join it on shutdown. mThread = PR_CreateThread(PR_USER_THREAD, WatchdogMain, this, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_JOINABLE_THREAD, kWatchdogStackSize); + PR_JOINABLE_THREAD, watchdogStackSize); if (!mThread) { MOZ_CRASH("PR_CreateThread failed!"); } // WatchdogMain acquires the lock and then asserts mInitialized. So // make sure to set mInitialized before releasing the lock here so // that it's atomic with the creation of the thread. mInitialized = true; # HG changeset patch # User stransky # Date 1628058287 0 # Node ID 600365d8b24068e8105773830270cf86478aa487 # Parent 7f9b9624c400dc847dc0053ebe35fbe63353a3d2 Bug 1721326 - Use small stack for DoClone(). r=jld, a=RyanVM Patch author is Florian Weimer Differential Revision: https://phabricator.services.mozilla.com/D120709 diff --git a/security/sandbox/linux/launch/SandboxLaunch.cpp b/security/sandbox/linux/launch/SandboxLaunch.cpp --- a/security/sandbox/linux/launch/SandboxLaunch.cpp +++ b/security/sandbox/linux/launch/SandboxLaunch.cpp @@ -504,18 +504,17 @@ static int CloneCallee(void* aPtr) { // stack, not switch stacks. // // Valgrind would disapprove of using clone() without CLONE_VM; // Chromium uses the raw syscall as a workaround in that case, but // we don't currently support sandboxing under valgrind. MOZ_NEVER_INLINE MOZ_ASAN_BLACKLIST static pid_t DoClone(int aFlags, jmp_buf* aCtx) { static constexpr size_t kStackAlignment = 16; - uint8_t miniStack[PTHREAD_STACK_MIN] - __attribute__((aligned(kStackAlignment))); + uint8_t miniStack[4096] __attribute__((aligned(kStackAlignment))); #ifdef __hppa__ void* stackPtr = miniStack; #else void* stackPtr = ArrayEnd(miniStack); #endif return clone(CloneCallee, stackPtr, aFlags, aCtx); } @@ -526,23 +525,29 @@ MOZ_NEVER_INLINE MOZ_ASAN_BLACKLIST stat static pid_t ForkWithFlags(int aFlags) { // Don't allow flags that would share the address space, or // require clone() arguments we're not passing: static const int kBadFlags = CLONE_VM | CLONE_VFORK | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID; MOZ_RELEASE_ASSERT((aFlags & kBadFlags) == 0); + // Block signals due to small stack in DoClone. + sigset_t oldSigs; + BlockAllSignals(&oldSigs); + + int ret = 0; jmp_buf ctx; if (setjmp(ctx) == 0) { // In the parent and just called setjmp: - return DoClone(aFlags | SIGCHLD, &ctx); + ret = DoClone(aFlags | SIGCHLD, &ctx); } + RestoreSignals(&oldSigs); // In the child and have longjmp'ed: - return 0; + return ret; } static bool WriteStringToFile(const char* aPath, const char* aStr, const size_t aLen) { int fd = open(aPath, O_WRONLY); if (fd < 0) { return false; }