From aa4fee503ced1385140f23c09a093f63c6290349 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Wed, 30 Jul 2014 16:49:43 +0100 Subject: [PATCH] Backed out changeset d50d7e88f35e (bug 1012951) for LSan failures --- configure.in | 23 --- content/media/gmp/GMPChild.cpp | 9 - dom/ipc/ContentChild.cpp | 2 +- security/sandbox/linux/Sandbox.cpp | 114 +++--------- security/sandbox/linux/Sandbox.h | 7 +- security/sandbox/linux/SandboxFilter.cpp | 212 +++++------------------ security/sandbox/linux/SandboxFilter.h | 26 +-- toolkit/toolkit.mozbuild | 2 +- 8 files changed, 74 insertions(+), 321 deletions(-) diff --git a/configure.in b/configure.in index e649037801c..e3a54436822 100644 --- a/configure.in +++ b/configure.in @@ -3844,7 +3844,6 @@ MOZ_PAY= MOZ_AUDIO_CHANNEL_MANAGER= NSS_NO_LIBPKIX= MOZ_CONTENT_SANDBOX= -MOZ_GMP_SANDBOX= JSGC_USE_EXACT_ROOTING=1 JSGC_GENERATIONAL= @@ -6406,28 +6405,6 @@ fi AC_SUBST(MOZ_CONTENT_SANDBOX) -dnl ======================================================== -dnl = Gecko Media Plugin sandboxing -dnl ======================================================== -case $OS_TARGET in -WINNT) - MOZ_GMP_SANDBOX=1 - ;; -Linux) - case $CPU_ARCH in - x86_64|x86) - MOZ_GMP_SANDBOX=1 - ;; - esac - ;; -esac - -if test -n "$MOZ_GMP_SANDBOX"; then - AC_DEFINE(MOZ_GMP_SANDBOX) -fi - -AC_SUBST(MOZ_GMP_SANDBOX) - dnl ======================================================== dnl = dnl = Module specific options diff --git a/content/media/gmp/GMPChild.cpp b/content/media/gmp/GMPChild.cpp index 15b656e6296..f6bb47b1901 100644 --- a/content/media/gmp/GMPChild.cpp +++ b/content/media/gmp/GMPChild.cpp @@ -26,8 +26,6 @@ using mozilla::dom::CrashReporterChild; #if defined(XP_WIN) #define TARGET_SANDBOX_EXPORTS #include "mozilla/sandboxTarget.h" -#elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) -#include "mozilla/Sandbox.h" #endif namespace mozilla { @@ -100,13 +98,6 @@ GMPChild::LoadPluginLibrary(const std::string& aPluginPath) nsAutoCString nativePath; libFile->GetNativePath(nativePath); - -#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX) - // Enable sandboxing here -- we know the plugin file's path, but - // this process's execution hasn't been affected by its content yet. - mozilla::SetMediaPluginSandbox(nativePath.get()); -#endif - mLib = PR_LoadLibrary(nativePath.get()); if (!mLib) { return false; diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 5cda5fb80ca..c9808a08be4 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -918,7 +918,7 @@ ContentChild::RecvSetProcessSandbox() // at some point; see bug 880808. #if defined(MOZ_CONTENT_SANDBOX) #if defined(XP_LINUX) - SetContentProcessSandbox(); + SetCurrentProcessSandbox(); #elif defined(XP_WIN) mozilla::SandboxTarget::Instance()->StartSandbox(); #endif diff --git a/security/sandbox/linux/Sandbox.cpp b/security/sandbox/linux/Sandbox.cpp index 800a6663ff1..654d81c00bc 100644 --- a/security/sandbox/linux/Sandbox.cpp +++ b/security/sandbox/linux/Sandbox.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include "mozilla/Atomics.h" #include "mozilla/NullPtr.h" @@ -37,8 +36,10 @@ #include #endif +#if defined(MOZ_CONTENT_SANDBOX) #include "linux_seccomp.h" #include "SandboxFilter.h" +#endif #ifdef MOZ_LOGGING #define FORCE_PR_LOG 1 @@ -59,14 +60,6 @@ static PRLogModuleInfo* gSeccompSandboxLog; #define LOG_ERROR(args...) #endif -#ifdef MOZ_GMP_SANDBOX -// For media plugins, we can start the sandbox before we dlopen the -// module, so we have to pre-open the file and simulate the sandboxed -// open(). -static int gMediaPluginFileDesc = -1; -static nsCString gMediaPluginFilePath; -#endif - /** * Log JS stack info in the same place as the sandbox violation * message. Useful in case the responsible code is JS and all we have @@ -144,27 +137,6 @@ Reporter(int nr, siginfo_t *info, void *void_context) args[4] = SECCOMP_PARM5(ctx); args[5] = SECCOMP_PARM6(ctx); -#ifdef MOZ_GMP_SANDBOX - if (syscall_nr == __NR_open && !gMediaPluginFilePath.IsEmpty()) { - const char *path = reinterpret_cast(args[0]); - int flags = int(args[1]); - - if ((flags & O_ACCMODE) != O_RDONLY) { - LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)", - path, flags); - } else if (strcmp(path, gMediaPluginFilePath.get()) != 0) { - LOG_ERROR("attempt to open file %s which is not the media plugin %s", - path, gMediaPluginFilePath.get()); - } else if (gMediaPluginFileDesc == -1) { - LOG_ERROR("multiple opens of media plugin file unimplemented"); - } else { - SECCOMP_RESULT(ctx) = gMediaPluginFileDesc; - gMediaPluginFileDesc = -1; - return; - } - } -#endif - LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu" " %lu %lu %lu. Killing process.", pid, syscall_nr, args[0], args[1], args[2], args[3], args[4], args[5]); @@ -282,7 +254,8 @@ SetThreadSandbox() { bool didAnything = false; - if (prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) { + if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr && + prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) { if (InstallSyscallFilter(sSetSandboxFilter) == 0) { didAnything = true; } @@ -312,19 +285,19 @@ SetThreadSandboxHandler(int signum) } static void -BroadcastSetThreadSandbox(SandboxType aType) +BroadcastSetThreadSandbox() { int signum; - pid_t pid, tid, myTid; + pid_t pid, tid; DIR *taskdp; struct dirent *de; - SandboxFilter filter(&sSetSandboxFilter, aType, - PR_GetEnv("MOZ_SANDBOX_VERBOSE")); + SandboxFilter filter(&sSetSandboxFilter, + PR_GetEnv("MOZ_CONTENT_SANDBOX_VERBOSE")); static_assert(sizeof(mozilla::Atomic) == sizeof(int), "mozilla::Atomic isn't represented by an int"); + MOZ_ASSERT(NS_IsMainThread()); pid = getpid(); - myTid = syscall(__NR_gettid); taskdp = opendir("/proc/self/task"); if (taskdp == nullptr) { LOG_ERROR("opendir /proc/self/task: %s\n", strerror(errno)); @@ -357,9 +330,9 @@ BroadcastSetThreadSandbox(SandboxType aType) // Not a task ID. continue; } - if (tid == myTid) { - // Drop this thread's privileges last, below, so we can - // continue to signal other threads. + if (tid == pid) { + // Drop the main thread's privileges last, below, so + // we can continue to signal other threads. continue; } // Reset the futex cell and signal. @@ -452,9 +425,14 @@ IsSandboxingSupported(void) return prctl(PR_GET_SECCOMP) != -1; } -// Common code for sandbox startup. -static void -SetCurrentProcessSandbox(SandboxType aType) +/** + * Starts the seccomp sandbox for this process and sets user/group-based privileges. + * Should be called only once, and before any potentially harmful content is loaded. + * + * Should normally make the process exit on failure. +*/ +void +SetCurrentProcessSandbox() { #if !defined(ANDROID) && defined(PR_LOGGING) if (!gSeccompSandboxLog) { @@ -468,60 +446,10 @@ SetCurrentProcessSandbox(SandboxType aType) } if (IsSandboxingSupported()) { - BroadcastSetThreadSandbox(aType); + BroadcastSetThreadSandbox(); } } -#ifdef MOZ_CONTENT_SANDBOX -/** - * Starts the seccomp sandbox for a content process. Should be called - * only once, and before any potentially harmful content is loaded. - * - * Will normally make the process exit on failure. -*/ -void -SetContentProcessSandbox() -{ - if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) { - return; - } - - SetCurrentProcessSandbox(kSandboxContentProcess); -} -#endif // MOZ_CONTENT_SANDBOX - -#ifdef MOZ_GMP_SANDBOX -/** - * Starts the seccomp sandbox for a media plugin process. Should be - * called only once, and before any potentially harmful content is - * loaded -- including the plugin itself, if it's considered untrusted. - * - * The file indicated by aFilePath, if non-null, can be open()ed once - * read-only after the sandbox starts; it should be the .so file - * implementing the not-yet-loaded plugin. - * - * Will normally make the process exit on failure. -*/ -void -SetMediaPluginSandbox(const char *aFilePath) -{ - if (PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) { - return; - } - - if (aFilePath) { - gMediaPluginFilePath.Assign(aFilePath); - gMediaPluginFileDesc = open(aFilePath, O_RDONLY | O_CLOEXEC); - if (gMediaPluginFileDesc == -1) { - LOG_ERROR("failed to open plugin file %s: %s", aFilePath, strerror(errno)); - MOZ_CRASH(); - } - } - // Finally, start the sandbox. - SetCurrentProcessSandbox(kSandboxMediaPlugin); -} -#endif // MOZ_GMP_SANDBOX - } // namespace mozilla diff --git a/security/sandbox/linux/Sandbox.h b/security/sandbox/linux/Sandbox.h index d8a3891ceb1..c9e2be7133f 100644 --- a/security/sandbox/linux/Sandbox.h +++ b/security/sandbox/linux/Sandbox.h @@ -9,12 +9,7 @@ namespace mozilla { -#ifdef MOZ_CONTENT_SANDBOX -void SetContentProcessSandbox(); -#endif -#ifdef MOZ_GMP_SANDBOX -void SetMediaPluginSandbox(const char *aFilePath); -#endif +void SetCurrentProcessSandbox(); } // namespace mozilla diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp index 8521b80e2bd..6a506d8d701 100644 --- a/security/sandbox/linux/SandboxFilter.cpp +++ b/security/sandbox/linux/SandboxFilter.cpp @@ -14,26 +14,49 @@ #include "mozilla/NullPtr.h" #include -#include -#include -#include -#include -#include -#include #include +#include +#include namespace mozilla { class SandboxFilterImpl : public SandboxAssembler { + void Build(); public: - virtual void Build() = 0; - virtual ~SandboxFilterImpl() { } + SandboxFilterImpl() { + Build(); + Finish(); + } }; -// Some helper macros to make the code that builds the filter more -// readable, and to help deal with differences among architectures. +SandboxFilter::SandboxFilter(const sock_fprog** aStored, bool aVerbose) + : mStored(aStored) +{ + MOZ_ASSERT(*mStored == nullptr); + std::vector filterVec; + { + SandboxFilterImpl impl; + impl.Compile(&filterVec, aVerbose); + } + mProg = new sock_fprog; + mProg->len = filterVec.size(); + mProg->filter = mFilter = new sock_filter[mProg->len]; + for (size_t i = 0; i < mProg->len; ++i) { + mFilter[i] = filterVec[i]; + } + *mStored = mProg; +} +SandboxFilter::~SandboxFilter() +{ + *mStored = nullptr; + delete[] mFilter; + delete mProg; +} + +void +SandboxFilterImpl::Build() { #define SYSCALL_EXISTS(name) (defined(__NR_##name)) #define SYSCALL(name) (Condition(__NR_##name)) @@ -46,40 +69,32 @@ public: Condition(__NR_##name, arg, argValues); \ }) -// Some architectures went through a transition from 32-bit to -// 64-bit off_t and had to version all the syscalls that referenced -// it; others (newer and/or 64-bit ones) didn't. Adjust the -// conditional as needed. + // Some architectures went through a transition from 32-bit to + // 64-bit off_t and had to version all the syscalls that referenced + // it; others (newer and/or 64-bit ones) didn't. Adjust the + // conditional as needed. #if SYSCALL_EXISTS(stat64) #define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(versioned) #else #define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(plain) #endif -// i386 multiplexes all the socket-related interfaces into a single -// syscall. + // i386 multiplexes all the socket-related interfaces into a single + // syscall. #if SYSCALL_EXISTS(socketcall) #define SOCKETCALL(name, NAME) SYSCALL_WITH_ARG(socketcall, 0, SYS_##NAME) #else #define SOCKETCALL(name, NAME) SYSCALL(name) #endif -// i386 multiplexes all the SysV-IPC-related interfaces into a single -// syscall. + // i386 multiplexes all the SysV-IPC-related interfaces into a single + // syscall. #if SYSCALL_EXISTS(ipc) #define SYSVIPCCALL(name, NAME) SYSCALL_WITH_ARG(ipc, 0, NAME) #else #define SYSVIPCCALL(name, NAME) SYSCALL(name) #endif -#ifdef MOZ_CONTENT_SANDBOX -class SandboxFilterImplContent : public SandboxFilterImpl { -protected: - virtual void Build() MOZ_OVERRIDE; -}; - -void -SandboxFilterImplContent::Build() { /* Most used system calls should be at the top of the whitelist * for performance reasons. The whitelist BPF filter exits after * processing any ALLOW_SYSCALL macro. @@ -310,150 +325,5 @@ SandboxFilterImplContent::Build() { Allow(SYSCALL(exit_group)); Allow(SYSCALL(exit)); } -#endif // MOZ_CONTENT_SANDBOX - -#ifdef MOZ_GMP_SANDBOX -class SandboxFilterImplGMP : public SandboxFilterImpl { -protected: - virtual void Build() MOZ_OVERRIDE; -}; - -void SandboxFilterImplGMP::Build() { - // As for content processes, check the most common syscalls first. - - Allow(SYSCALL_WITH_ARG(clock_gettime, 0, CLOCK_MONOTONIC, CLOCK_REALTIME)); - Allow(SYSCALL(futex)); - Allow(SYSCALL(gettimeofday)); - Allow(SYSCALL(poll)); - Allow(SYSCALL(write)); - Allow(SYSCALL(read)); - Allow(SYSCALL(epoll_wait)); - Allow(SOCKETCALL(recvmsg, RECVMSG)); - Allow(SOCKETCALL(sendmsg, SENDMSG)); - Allow(SYSCALL(time)); - - // Nothing after this line is performance-critical. - -#if SYSCALL_EXISTS(mmap2) - Allow(SYSCALL(mmap2)); -#else - Allow(SYSCALL(mmap)); -#endif - Allow(SYSCALL_LARGEFILE(fstat, fstat64)); - Allow(SYSCALL(munmap)); - - Allow(SYSCALL(gettid)); - - // The glibc source hasn't changed the thread creation clone flags - // since 2004, so this *should* be safe to hard-code. Bionic is - // different, but MOZ_GMP_SANDBOX isn't supported there yet. - // - // At minimum we should require CLONE_THREAD, so that a single - // SIGKILL from the parent will destroy all descendant tasks. In - // general, pinning down as much of the flags word as possible is a - // good idea, because it exposes a lot of subtle (and probably not - // well tested in all cases) kernel functionality. - // - // WARNING: s390 and cris pass the flags in a different arg -- see - // CLONE_BACKWARDS2 in arch/Kconfig in the kernel source -- but we - // don't support seccomp-bpf on those archs yet. - static const int new_thread_flags = CLONE_VM | CLONE_FS | CLONE_FILES | - CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | - CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; - Allow(SYSCALL_WITH_ARG(clone, 0, new_thread_flags)); - - Allow(SYSCALL_WITH_ARG(prctl, 0, PR_GET_SECCOMP, PR_SET_NAME)); - -#if SYSCALL_EXISTS(set_robust_list) - Allow(SYSCALL(set_robust_list)); -#endif - - // NSPR can call this when creating a thread, but it will accept a - // polite "no". - Deny(EACCES, SYSCALL(getpriority)); - - Allow(SYSCALL(mprotect)); - Allow(SYSCALL_WITH_ARG(madvise, 2, MADV_DONTNEED)); - -#if SYSCALL_EXISTS(sigreturn) - Allow(SYSCALL(sigreturn)); -#endif - Allow(SYSCALL(rt_sigreturn)); - - Allow(SYSCALL(restart_syscall)); - Allow(SYSCALL(close)); - - // "Sleeping for 300 seconds" in debug crashes; possibly other uses. - Allow(SYSCALL(nanosleep)); - - // For the crash reporter: -#if SYSCALL_EXISTS(sigprocmask) - Allow(SYSCALL(sigprocmask)); -#endif - Allow(SYSCALL(rt_sigprocmask)); -#if SYSCALL_EXISTS(sigaction) - Allow(SYSCALL(sigaction)); -#endif - Allow(SYSCALL(rt_sigaction)); - Allow(SOCKETCALL(socketpair, SOCKETPAIR)); - Allow(SYSCALL_WITH_ARG(tgkill, 0, uint32_t(getpid()))); - Allow(SYSCALL_WITH_ARG(prctl, 0, PR_SET_DUMPABLE)); - - // Note for when GMP is supported on an ARM platform: Add whichever - // of the ARM-specific syscalls are needed for this type of process. - - Allow(SYSCALL(epoll_ctl)); - Allow(SYSCALL(exit)); - Allow(SYSCALL(exit_group)); -} -#endif // MOZ_GMP_SANDBOX - -SandboxFilter::SandboxFilter(const sock_fprog** aStored, SandboxType aType, - bool aVerbose) - : mStored(aStored) -{ - MOZ_ASSERT(*mStored == nullptr); - std::vector filterVec; - SandboxFilterImpl *impl; - - switch (aType) { - case kSandboxContentProcess: -#ifdef MOZ_CONTENT_SANDBOX - impl = new SandboxFilterImplContent(); -#else - MOZ_CRASH("Content process sandboxing not supported in this build!"); -#endif - break; - case kSandboxMediaPlugin: -#ifdef MOZ_GMP_SANDBOX - impl = new SandboxFilterImplGMP(); -#else - MOZ_CRASH("Gecko Media Plugin process sandboxing not supported in this" - " build!"); -#endif - break; - default: - MOZ_CRASH("Nonexistent sandbox type!"); - } - impl->Build(); - impl->Finish(); - impl->Compile(&filterVec, aVerbose); - delete impl; - - mProg = new sock_fprog; - mProg->len = filterVec.size(); - mProg->filter = mFilter = new sock_filter[mProg->len]; - for (size_t i = 0; i < mProg->len; ++i) { - mFilter[i] = filterVec[i]; - } - *mStored = mProg; -} - -SandboxFilter::~SandboxFilter() -{ - *mStored = nullptr; - delete[] mFilter; - delete mProg; -} } diff --git a/security/sandbox/linux/SandboxFilter.h b/security/sandbox/linux/SandboxFilter.h index 861fd12bb1d..a00dea2cf4b 100644 --- a/security/sandbox/linux/SandboxFilter.h +++ b/security/sandbox/linux/SandboxFilter.h @@ -11,25 +11,17 @@ struct sock_fprog; struct sock_filter; namespace mozilla { - -enum SandboxType { - kSandboxContentProcess, - kSandboxMediaPlugin -}; - -class SandboxFilter { - sock_filter *mFilter; - sock_fprog *mProg; - const sock_fprog **mStored; -public: + class SandboxFilter { + sock_filter *mFilter; + sock_fprog *mProg; + const sock_fprog **mStored; + public: // RAII: on construction, builds the filter and stores it in the // provided variable (with optional logging); on destruction, frees // the filter and nulls out the pointer. - SandboxFilter(const sock_fprog** aStored, SandboxType aBox, - bool aVerbose = false); - ~SandboxFilter(); -}; - -} // namespace mozilla + SandboxFilter(const sock_fprog** aStored, bool aVerbose = false); + ~SandboxFilter(); + }; +} #endif diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild index 28e52f77acb..20b9d686514 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -6,7 +6,7 @@ if CONFIG['LIBXUL_SDK']: error('toolkit.mozbuild is not compatible with --enable-libxul-sdk=') -if CONFIG['MOZ_CONTENT_SANDBOX'] or CONFIG['MOZ_GMP_SANDBOX']: +if CONFIG['MOZ_CONTENT_SANDBOX'] or (CONFIG['OS_ARCH'] == 'WINNT'): add_tier_dir('sandbox', 'security/sandbox') # Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator