mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1012951 - Add Linux sandboxing for GeckoMediaPlugin processes. r=kang r=ted
--HG-- extra : rebase_source : 1b890000d5b8d2a8954cdd1118a1023eba829c29
This commit is contained in:
parent
2d6844764c
commit
4d6ff2569b
23
configure.in
23
configure.in
@ -3843,6 +3843,7 @@ MOZ_PAY=
|
||||
MOZ_AUDIO_CHANNEL_MANAGER=
|
||||
NSS_NO_LIBPKIX=
|
||||
MOZ_CONTENT_SANDBOX=
|
||||
MOZ_GMP_SANDBOX=
|
||||
JSGC_USE_EXACT_ROOTING=1
|
||||
JSGC_GENERATIONAL=
|
||||
|
||||
@ -6394,6 +6395,28 @@ 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
|
||||
|
@ -27,6 +27,8 @@ 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 {
|
||||
@ -99,6 +101,13 @@ 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;
|
||||
|
@ -918,7 +918,7 @@ ContentChild::RecvSetProcessSandbox()
|
||||
// at some point; see bug 880808.
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_LINUX)
|
||||
SetCurrentProcessSandbox();
|
||||
SetContentProcessSandbox();
|
||||
#elif defined(XP_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#endif
|
||||
|
@ -19,12 +19,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prenv.h"
|
||||
|
||||
@ -37,10 +37,8 @@
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#include "linux_seccomp.h"
|
||||
#include "SandboxFilter.h"
|
||||
#endif
|
||||
|
||||
// See definition of SandboxDie, below.
|
||||
#include "sandbox/linux/seccomp-bpf/die.h"
|
||||
@ -52,6 +50,14 @@ namespace mozilla {
|
||||
#define LOG_ERROR(fmt, args...) fprintf(stderr, "Sandbox: " fmt, ## 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 const char *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
|
||||
@ -129,6 +135,27 @@ 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) {
|
||||
const char *path = reinterpret_cast<const char*>(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) != 0) {
|
||||
LOG_ERROR("attempt to open file %s which is not the media plugin %s",
|
||||
path, gMediaPluginFilePath);
|
||||
} 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]);
|
||||
@ -246,8 +273,7 @@ SetThreadSandbox()
|
||||
{
|
||||
bool didAnything = false;
|
||||
|
||||
if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
|
||||
prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
|
||||
if (prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
|
||||
if (InstallSyscallFilter(sSetSandboxFilter) == 0) {
|
||||
didAnything = true;
|
||||
}
|
||||
@ -277,19 +303,19 @@ SetThreadSandboxHandler(int signum)
|
||||
}
|
||||
|
||||
static void
|
||||
BroadcastSetThreadSandbox()
|
||||
BroadcastSetThreadSandbox(SandboxType aType)
|
||||
{
|
||||
int signum;
|
||||
pid_t pid, tid;
|
||||
pid_t pid, tid, myTid;
|
||||
DIR *taskdp;
|
||||
struct dirent *de;
|
||||
SandboxFilter filter(&sSetSandboxFilter,
|
||||
PR_GetEnv("MOZ_CONTENT_SANDBOX_VERBOSE"));
|
||||
SandboxFilter filter(&sSetSandboxFilter, aType,
|
||||
PR_GetEnv("MOZ_SANDBOX_VERBOSE"));
|
||||
|
||||
static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
|
||||
"mozilla::Atomic<int> 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));
|
||||
@ -322,9 +348,9 @@ BroadcastSetThreadSandbox()
|
||||
// Not a task ID.
|
||||
continue;
|
||||
}
|
||||
if (tid == pid) {
|
||||
// Drop the main thread's privileges last, below, so
|
||||
// we can continue to signal other threads.
|
||||
if (tid == myTid) {
|
||||
// Drop this thread's privileges last, below, so we can
|
||||
// continue to signal other threads.
|
||||
continue;
|
||||
}
|
||||
// Reset the futex cell and signal.
|
||||
@ -417,24 +443,69 @@ IsSandboxingSupported(void)
|
||||
return prctl(PR_GET_SECCOMP) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
// Common code for sandbox startup.
|
||||
static void
|
||||
SetCurrentProcessSandbox(SandboxType aType)
|
||||
{
|
||||
if (InstallSyscallReporter()) {
|
||||
LOG_ERROR("install_syscall_reporter() failed\n");
|
||||
}
|
||||
|
||||
if (IsSandboxingSupported()) {
|
||||
BroadcastSetThreadSandbox();
|
||||
BroadcastSetThreadSandbox(aType);
|
||||
}
|
||||
}
|
||||
|
||||
#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 = strdup(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
|
||||
|
||||
|
||||
|
@ -9,7 +9,12 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
void SetCurrentProcessSandbox();
|
||||
#ifdef MOZ_CONTENT_SANDBOX
|
||||
void SetContentProcessSandbox();
|
||||
#endif
|
||||
#ifdef MOZ_GMP_SANDBOX
|
||||
void SetMediaPluginSandbox(const char *aFilePath);
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -14,49 +14,26 @@
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/ipc.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/prctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class SandboxFilterImpl : public SandboxAssembler
|
||||
{
|
||||
void Build();
|
||||
public:
|
||||
SandboxFilterImpl() {
|
||||
Build();
|
||||
Finish();
|
||||
}
|
||||
virtual void Build() = 0;
|
||||
virtual ~SandboxFilterImpl() { }
|
||||
};
|
||||
|
||||
SandboxFilter::SandboxFilter(const sock_fprog** aStored, bool aVerbose)
|
||||
: mStored(aStored)
|
||||
{
|
||||
MOZ_ASSERT(*mStored == nullptr);
|
||||
std::vector<struct sock_filter> 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;
|
||||
}
|
||||
// Some helper macros to make the code that builds the filter more
|
||||
// readable, and to help deal with differences among architectures.
|
||||
|
||||
SandboxFilter::~SandboxFilter()
|
||||
{
|
||||
*mStored = nullptr;
|
||||
delete[] mFilter;
|
||||
delete mProg;
|
||||
}
|
||||
|
||||
void
|
||||
SandboxFilterImpl::Build() {
|
||||
#define SYSCALL_EXISTS(name) (defined(__NR_##name))
|
||||
|
||||
#define SYSCALL(name) (Condition(__NR_##name))
|
||||
@ -95,6 +72,14 @@ SandboxFilterImpl::Build() {
|
||||
#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.
|
||||
@ -329,5 +314,159 @@ SandboxFilterImpl::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(getpid));
|
||||
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));
|
||||
|
||||
// Stack bounds are obtained via pthread_getattr_np, which calls
|
||||
// this but doesn't actually need it:
|
||||
Deny(ENOSYS, SYSCALL(sched_getaffinity));
|
||||
|
||||
#ifdef MOZ_ASAN
|
||||
Allow(SYSCALL(sigaltstack));
|
||||
#endif
|
||||
|
||||
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<struct sock_filter> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,12 @@ struct sock_fprog;
|
||||
struct sock_filter;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum SandboxType {
|
||||
kSandboxContentProcess,
|
||||
kSandboxMediaPlugin
|
||||
};
|
||||
|
||||
class SandboxFilter {
|
||||
sock_filter *mFilter;
|
||||
sock_fprog *mProg;
|
||||
@ -19,9 +25,11 @@ namespace mozilla {
|
||||
// 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, bool aVerbose = false);
|
||||
SandboxFilter(const sock_fprog** aStored, SandboxType aBox,
|
||||
bool aVerbose = false);
|
||||
~SandboxFilter();
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
@ -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['OS_ARCH'] == 'WINNT'):
|
||||
if CONFIG['MOZ_CONTENT_SANDBOX'] or CONFIG['MOZ_GMP_SANDBOX']:
|
||||
add_tier_dir('sandbox', 'security/sandbox')
|
||||
|
||||
# Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator
|
||||
|
Loading…
Reference in New Issue
Block a user