Bug 859782 - Firefox cannot start without /proc (chroot) r=sphink
☠☠ backed out by 22ed5e1657aa ☠ ☠
authorRichard Pospesel <richard>
Wed, 18 Apr 2018 13:41:00 +0300
changeset 414533 0ab0d909476f55bd58181485889f0a31d032b308
parent 414532 c30785b6f3f7b043377846f7e4d0dc0fd0a16451
child 414534 363cc3b4dd41a2c5469fb03d72451e942687c73c
push id33871
push usercsabou@mozilla.com
push dateThu, 19 Apr 2018 22:30:08 +0000
treeherdermozilla-central@5d73549d363f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssphink
bugs859782
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 859782 - Firefox cannot start without /proc (chroot) r=sphink
js/src/util/NativeStack.cpp
--- a/js/src/util/NativeStack.cpp
+++ b/js/src/util/NativeStack.cpp
@@ -56,16 +56,68 @@ void*
 js::GetNativeStackBaseImpl()
 {
     ucontext_t context;
     getcontext(&context);
     return static_cast<char*>(context.uc_stack.ss_sp) +
         context.uc_stack.ss_size;
 }
 
+#elif defined(XP_LINUX) && !defined(ANDROID)
+
+# include <dlfcn.h>
+# include <sys/syscall.h>
+static pid_t
+gettid()
+{
+    return syscall(__NR_gettid);
+}
+
+void*
+js::GetNativeStackBaseImpl()
+{
+    // On the main thread, get stack base from glibc's __libc_stack_end rather than pthread APIs
+    // to avoid filesystem calls /proc/self/maps.  Non-main threads spawned with pthreads can read
+    // this information directly from their pthread struct, but the main thread must go parse
+    // /proc/self/maps to figure the mapped stack address space ranges.  We want to avoid reading
+    // from /proc/ so that firefox can run in sandboxed environments where /proc may not be mounted
+    if(gettid() == getpid()) {
+        void** pLibcStackEnd = (void**)dlsym(RTLD_DEFAULT, "__libc_stack_end");
+        // If __libc_stack_end is not found, architecture specific frame pointer hopping will need
+        // to be implemented.
+        MOZ_RELEASE_ASSERT(pLibcStackEnd, "__libc_stack_end unavailable, unable to setup stack range for JS");
+        void* stackBase = *pLibcStackEnd;
+        MOZ_RELEASE_ASSERT(stackBase, "invalid stack base, unable to setup stack range for JS");
+        // We don't need to fix stackBase, as it already roughly points to beginning of the stack
+        return stackBase;
+    }
+    // Non-main threads have the required info stored in memory, so no filesystem calls are made.
+    else {
+        pthread_t thread = pthread_self();
+        pthread_attr_t sattr;
+        pthread_attr_init(&sattr);
+        pthread_getattr_np(thread, &sattr);
+        // stackBase will be the *lowest* address on all architectures.
+        void* stackBase = nullptr;
+        size_t stackSize = 0;
+        int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+        if(rc) {
+            MOZ_CRASH();
+        }
+        MOZ_RELEASE_ASSERT(stackBase, "invalid stack base, unable to setup stack range for JS");
+        pthread_attr_destroy(&sattr);
+
+# if JS_STACK_GROWTH_DIRECTION > 0
+        return stackBase;
+# else
+        return static_cast<char*>(stackBase) + stackSize;
+# endif
+    }
+}
+
 #else /* XP_UNIX */
 
 void*
 js::GetNativeStackBaseImpl()
 {
     pthread_t thread = pthread_self();
 # if defined(XP_DARWIN) || defined(DARWIN)
     return pthread_get_stackaddr_np(thread);