Bug 920372 - Use Chromium seccomp-bpf compiler to dynamically build sandbox program. r=kang

This commit is contained in:
Jed Davis 2014-05-20 18:37:53 -07:00
parent 3b103d307f
commit 3a308504da
6 changed files with 489 additions and 164 deletions

View File

@ -47,6 +47,9 @@
#include "prlog.h"
#include "prenv.h"
// See definition of SandboxDie, below.
#include "sandbox/linux/seccomp-bpf/die.h"
namespace mozilla {
#if defined(ANDROID)
#define LOG_ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "Sandbox", ## args)
@ -206,7 +209,7 @@ InstallSyscallReporter(void)
* @see sock_fprog (the seccomp_prog).
*/
static int
InstallSyscallFilter(void)
InstallSyscallFilter(const sock_fprog *prog)
{
#ifdef MOZ_DMD
char* e = PR_GetEnv("DMD");
@ -221,9 +224,7 @@ InstallSyscallFilter(void)
return 1;
}
const sock_fprog *filter = GetSandboxFilter();
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)filter, 0, 0)) {
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)prog, 0, 0)) {
return 1;
}
return 0;
@ -235,6 +236,8 @@ static mozilla::Atomic<int> sSetSandboxDone;
// about:memory has the first 3 RT signals. (We should allocate
// signals centrally instead of hard-coding them like this.)
static const int sSetSandboxSignum = SIGRTMIN + 3;
// Pass the filter itself through a global.
static const sock_fprog *sSetSandboxFilter;
static bool
SetThreadSandbox()
@ -243,7 +246,7 @@ SetThreadSandbox()
if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
if (InstallSyscallFilter() == 0) {
if (InstallSyscallFilter(sSetSandboxFilter) == 0) {
didAnything = true;
}
/*
@ -277,6 +280,8 @@ BroadcastSetThreadSandbox()
pid_t pid, tid;
DIR *taskdp;
struct dirent *de;
SandboxFilter filter(&sSetSandboxFilter,
PR_GetEnv("MOZ_CONTENT_SANDBOX_VERBOSE"));
static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
"mozilla::Atomic<int> isn't represented by an int");
@ -425,3 +430,33 @@ SetCurrentProcessSandbox()
} // namespace mozilla
// "Polyfill" for sandbox::Die, the real version of which requires
// Chromium's logging code.
namespace sandbox {
void
Die::SandboxDie(const char* msg, const char* file, int line)
{
LOG_ERROR("%s:%d: %s\n", file, line, msg);
_exit(127);
}
} // namespace sandbox
// Stubs for unreached logging calls from Chromium CHECK() macro.
#include "base/logging.h"
namespace logging {
LogMessage::LogMessage(const char *file, int line, int)
: line_(line), file_(file)
{
MOZ_CRASH("Unexpected call to logging::LogMessage::LogMessage");
}
LogMessage::~LogMessage() {
MOZ_CRASH("Unexpected call to logging::LogMessage::~LogMessage");
}
} // namespace logging

View File

@ -0,0 +1,150 @@
/* -*- 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/. */
#include "SandboxAssembler.h"
#include "linux_seccomp.h"
#include "mozilla/NullPtr.h"
#include <errno.h>
using namespace sandbox;
namespace mozilla {
SandboxAssembler::SandboxAssembler()
{
mTail = LoadSyscall(nullptr);
mTailAlt = nullptr;
mHead = LoadArch(JmpEq(SECCOMP_ARCH, mTail, RetKill()));
}
void
SandboxAssembler::AppendCheck(Instruction *aCheck,
Instruction *aNewTail,
Instruction *aNewTailAlt)
{
mCode.JoinInstructions(mTail, aCheck);
if (mTailAlt != nullptr) {
mCode.JoinInstructions(mTailAlt, aCheck);
}
mTail = aNewTail;
mTailAlt = aNewTailAlt;
}
void
SandboxAssembler::Handle(const Condition &aCond, Instruction *aResult)
{
Instruction *checkArg, *noMatch;
if (!aCond.mCheckingArg) {
checkArg = aResult;
noMatch = nullptr;
} else {
const int8_t arg = aCond.mArgChecked;
noMatch = LoadSyscall(nullptr);
Instruction *checkArgLo = noMatch;
// Loop backwards, prepending checks onto the no-match base case.
for (size_t i = aCond.mArgValues.size(); i > 0; --i) {
checkArgLo = JmpEq(aCond.mArgValues[i - 1], aResult, checkArgLo);
}
checkArgLo = LoadArgLo(arg, checkArgLo);
checkArg = LoadArgHi(arg, JmpEq(0, checkArgLo, RetKill()));
}
Instruction *check = JmpEq(aCond.mSyscallNr, checkArg, nullptr);
AppendCheck(check, check, noMatch);
}
void
SandboxAssembler::Finish()
{
AppendCheck(RetKill(), nullptr, nullptr);
}
void
SandboxAssembler::Compile(std::vector<struct sock_filter> *aProgram,
bool aPrint)
{
mCode.Compile(mHead, aProgram);
if (aPrint) {
mCode.PrintProgram(*aProgram);
}
}
SandboxAssembler::~SandboxAssembler()
{
// The CodeGen destructor will clean up the Instruction graph.
}
Instruction *
SandboxAssembler::LoadArch(Instruction *aNext)
{
return mCode.MakeInstruction(BPF_LD + BPF_W + BPF_ABS,
SECCOMP_ARCH_IDX,
aNext);
}
Instruction *
SandboxAssembler::LoadSyscall(Instruction *aNext)
{
return mCode.MakeInstruction(BPF_LD + BPF_W + BPF_ABS,
SECCOMP_NR_IDX,
aNext);
}
Instruction *
SandboxAssembler::LoadArgHi(int aArg, Instruction *aNext)
{
return mCode.MakeInstruction(BPF_LD + BPF_W + BPF_ABS,
SECCOMP_ARG_MSB_IDX(aArg),
aNext);
}
Instruction *
SandboxAssembler::LoadArgLo(int aArg, Instruction *aNext)
{
return mCode.MakeInstruction(BPF_LD + BPF_W + BPF_ABS,
SECCOMP_ARG_LSB_IDX(aArg),
aNext);
}
Instruction *
SandboxAssembler::JmpEq(uint32_t aValue, Instruction *aThen, Instruction *aElse)
{
return mCode.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K,
aValue, aThen, aElse);
}
Instruction *
SandboxAssembler::RetAllow()
{
return mCode.MakeInstruction(BPF_RET + BPF_K,
SECCOMP_RET_ALLOW,
nullptr);
}
Instruction *
SandboxAssembler::RetDeny(int aErrno)
{
return mCode.MakeInstruction(BPF_RET + BPF_K,
SECCOMP_RET_ERRNO + aErrno,
nullptr);
}
Instruction *
SandboxAssembler::RetKill()
{
return mCode.MakeInstruction(BPF_RET + BPF_K,
#ifdef MOZ_CONTENT_SANDBOX_REPORTER
SECCOMP_RET_TRAP,
#else
SECCOMP_RET_KILL,
#endif
nullptr);
}
} // namespace mozilla

View File

@ -0,0 +1,97 @@
/* -*- 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_SandboxAssembler_h
#define mozilla_SandboxAssembler_h
#include "sandbox/linux/seccomp-bpf/codegen.h"
#include <vector>
#include "mozilla/Assertions.h"
using namespace sandbox;
namespace mozilla {
class SandboxAssembler {
public:
SandboxAssembler();
~SandboxAssembler();
class Condition {
friend class SandboxAssembler;
uint32_t mSyscallNr;
bool mCheckingArg;
uint8_t mArgChecked;
// This class retains a copy of the array, because C++11
// initializer_list isn't supported on all relevant platforms.
std::vector<uint32_t> mArgValues;
public:
// Match any instance of the given syscall, with any arguments.
explicit Condition(uint32_t aSyscallNr)
: mSyscallNr(aSyscallNr)
, mCheckingArg(false)
{ }
// Match the syscall only if the given argument is one of the
// values in the array specified. (If the argument isn't
// representable as uint32, the process is killed or signaled, as
// appropriate.)
template<size_t n>
Condition(uint32_t aSyscallNr, uint8_t aArgChecked,
const uint32_t (&aArgValues)[n])
: mSyscallNr(aSyscallNr)
, mCheckingArg(true)
, mArgChecked(aArgChecked)
, mArgValues(aArgValues, aArgValues + n)
{
MOZ_ASSERT(aArgChecked < sNumArgs);
}
};
// Allow syscalls matching this condition, if no earlier condition matched.
void Allow(const Condition &aCond) {
Handle(aCond, RetAllow());
}
// Cause syscalls matching this condition to fail with the given error, if
// no earlier condition matched.
void Deny(int aErrno, const Condition &aCond) {
Handle(aCond, RetDeny(aErrno));
}
void Finish();
void Compile(std::vector<struct sock_filter> *aProgram,
bool aPrint = false);
private:
CodeGen mCode;
// The entry point of the filter program.
Instruction *mHead;
// Pointer to an instruction with a null successor which needs to be filled
// in with the rest of the program; see CodeGen::JoinInstructions.
Instruction *mTail;
// In some cases we will have two such instructions; this, if not null, is
// that. (If we have more complicated conditions in the future, this may
// need to be generalized into a vector<Instruction*>.)
Instruction *mTailAlt;
Instruction *RetAllow();
Instruction *RetDeny(int aErrno);
Instruction *RetKill();
Instruction *LoadArch(Instruction *aNext);
Instruction *LoadSyscall(Instruction *aNext);
Instruction *LoadArgHi(int aArg, Instruction *aNext);
Instruction *LoadArgLo(int aArg, Instruction *aNext);
Instruction *JmpEq(uint32_t aValue, Instruction *aThen, Instruction *aElse);
void AppendCheck(Instruction *aCheck,
Instruction *aNewTail,
Instruction *aNewTailAlt);
void Handle(const Condition &aCond, Instruction* aResult);
static const uint8_t sNumArgs = 6;
};
}
#endif

View File

@ -5,30 +5,76 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SandboxFilter.h"
#include "SandboxAssembler.h"
#include "linux_seccomp.h"
#include "linux_syscalls.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/NullPtr.h"
#include <errno.h>
#include <unistd.h>
namespace mozilla {
#define SYSCALL_EXISTS(name) defined(__NR_##name)
class SandboxFilterImpl : public SandboxAssembler
{
void Build();
public:
SandboxFilterImpl() {
Build();
Finish();
}
};
static struct sock_filter seccomp_filter[] = {
VALIDATE_ARCHITECTURE,
EXAMINE_SYSCALL,
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;
}
SandboxFilter::~SandboxFilter()
{
*mStored = nullptr;
delete[] mFilter;
delete mProg;
}
void
SandboxFilterImpl::Build() {
#define SYSCALL_EXISTS(name) (defined(__NR_##name))
#define SYSCALL(name) (Condition(__NR_##name))
#if defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))
#define ARM_SYSCALL(name) (Condition(__ARM_NR_##name))
#endif
#define SYSCALL_WITH_ARG(name, arg, values...) ({ \
uint32_t argValues[] = { values }; \
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.
#if SYSCALL_EXISTS(stat64)
#define ALLOW_SYSCALL_LARGEFILE(plain, versioned) ALLOW_SYSCALL(versioned)
#define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(versioned)
#else
#define ALLOW_SYSCALL_LARGEFILE(plain, versioned) ALLOW_SYSCALL(plain)
#define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(plain)
#endif
/* Most used system calls should be at the top of the whitelist
@ -48,237 +94,220 @@ static struct sock_filter seccomp_filter[] = {
* 'strace -c -p <child pid>' for most used web apps.
*/
ALLOW_SYSCALL(futex),
Allow(SYSCALL(futex));
// FIXME, bug 920372: i386 multiplexes all the socket-related
// interfaces into a single syscall. We should check the selector.
#if SYSCALL_EXISTS(socketcall)
ALLOW_SYSCALL(socketcall),
Allow(SYSCALL(socketcall));
#else
ALLOW_SYSCALL(recvmsg),
ALLOW_SYSCALL(sendmsg),
Allow(SYSCALL(recvmsg));
Allow(SYSCALL(sendmsg));
#endif
// mmap2 is a little different from most off_t users, because it's
// passed in a register (so it's a problem for even a "new" 32-bit
// arch) -- and the workaround, mmap2, passes a page offset instead.
#if SYSCALL_EXISTS(mmap2)
ALLOW_SYSCALL(mmap2),
Allow(SYSCALL(mmap2));
#else
ALLOW_SYSCALL(mmap),
Allow(SYSCALL(mmap));
#endif
/* B2G specific high-frequency syscalls */
#ifdef MOZ_WIDGET_GONK
ALLOW_SYSCALL(clock_gettime),
ALLOW_SYSCALL(epoll_wait),
ALLOW_SYSCALL(gettimeofday),
Allow(SYSCALL(clock_gettime));
Allow(SYSCALL(epoll_wait));
Allow(SYSCALL(gettimeofday));
#endif
ALLOW_SYSCALL(read),
ALLOW_SYSCALL(write),
Allow(SYSCALL(read));
Allow(SYSCALL(write));
// 32-bit lseek is used, at least on Android, to implement ANSI fseek.
#if SYSCALL_EXISTS(_llseek)
ALLOW_SYSCALL(_llseek),
Allow(SYSCALL(_llseek));
#endif
ALLOW_SYSCALL(lseek),
Allow(SYSCALL(lseek));
// Android also uses 32-bit ftruncate.
ALLOW_SYSCALL(ftruncate),
Allow(SYSCALL(ftruncate));
#if SYSCALL_EXISTS(ftruncate64)
ALLOW_SYSCALL(ftruncate64),
Allow(SYSCALL(ftruncate64));
#endif
/* ioctl() is for GL. Remove when GL proxy is implemented.
* Additionally ioctl() might be a place where we want to have
* argument filtering */
ALLOW_SYSCALL(ioctl),
ALLOW_SYSCALL(close),
ALLOW_SYSCALL(munmap),
ALLOW_SYSCALL(mprotect),
ALLOW_SYSCALL(writev),
ALLOW_SYSCALL(clone),
ALLOW_SYSCALL(brk),
Allow(SYSCALL(ioctl));
Allow(SYSCALL(close));
Allow(SYSCALL(munmap));
Allow(SYSCALL(mprotect));
Allow(SYSCALL(writev));
Allow(SYSCALL(clone));
Allow(SYSCALL(brk));
#if SYSCALL_EXISTS(set_thread_area)
ALLOW_SYSCALL(set_thread_area),
Allow(SYSCALL(set_thread_area));
#endif
ALLOW_SYSCALL(getpid),
ALLOW_SYSCALL(gettid),
ALLOW_SYSCALL(getrusage),
ALLOW_SYSCALL(madvise),
ALLOW_SYSCALL(dup),
ALLOW_SYSCALL(nanosleep),
ALLOW_SYSCALL(poll),
Allow(SYSCALL(getpid));
Allow(SYSCALL(gettid));
Allow(SYSCALL(getrusage));
Allow(SYSCALL(madvise));
Allow(SYSCALL(dup));
Allow(SYSCALL(nanosleep));
Allow(SYSCALL(poll));
// select()'s arguments used to be passed by pointer as a struct.
#if SYSCALL_EXISTS(_newselect)
ALLOW_SYSCALL(_newselect),
Allow(SYSCALL(_newselect));
#else
ALLOW_SYSCALL(select),
Allow(SYSCALL(select));
#endif
// Some archs used to have 16-bit uid/gid instead of 32-bit.
#if SYSCALL_EXISTS(getuid32)
ALLOW_SYSCALL(getuid32),
ALLOW_SYSCALL(geteuid32),
Allow(SYSCALL(getuid32));
Allow(SYSCALL(geteuid32));
#else
ALLOW_SYSCALL(getuid),
ALLOW_SYSCALL(geteuid),
Allow(SYSCALL(getuid));
Allow(SYSCALL(geteuid));
#endif
// Some newer archs (e.g., x64 and x32) have only rt_sigreturn, but
// ARM has and uses both syscalls -- rt_sigreturn for SA_SIGINFO
// handlers and classic sigreturn otherwise.
#if SYSCALL_EXISTS(sigreturn)
ALLOW_SYSCALL(sigreturn),
Allow(SYSCALL(sigreturn));
#endif
ALLOW_SYSCALL(rt_sigreturn),
ALLOW_SYSCALL_LARGEFILE(fcntl, fcntl64),
Allow(SYSCALL(rt_sigreturn));
Allow(SYSCALL_LARGEFILE(fcntl, fcntl64));
/* Must remove all of the following in the future, when no longer used */
/* open() is for some legacy APIs such as font loading. */
/* See bug 906996 for removing unlink(). */
ALLOW_SYSCALL_LARGEFILE(fstat, fstat64),
ALLOW_SYSCALL_LARGEFILE(stat, stat64),
ALLOW_SYSCALL_LARGEFILE(lstat, lstat64),
Allow(SYSCALL_LARGEFILE(fstat, fstat64));
Allow(SYSCALL_LARGEFILE(stat, stat64));
Allow(SYSCALL_LARGEFILE(lstat, lstat64));
// FIXME, bug 920372: see above.
#if !SYSCALL_EXISTS(socketcall)
ALLOW_SYSCALL(socketpair),
DENY_SYSCALL(socket, EACCES),
Allow(SYSCALL(socketpair));
Deny(EACCES, SYSCALL(socket));
#endif
ALLOW_SYSCALL(open),
ALLOW_SYSCALL(readlink), /* Workaround for bug 964455 */
ALLOW_SYSCALL(prctl),
ALLOW_SYSCALL(access),
ALLOW_SYSCALL(unlink),
ALLOW_SYSCALL(fsync),
ALLOW_SYSCALL(msync),
Allow(SYSCALL(open));
Allow(SYSCALL(readlink)); /* Workaround for bug 964455 */
Allow(SYSCALL(prctl));
Allow(SYSCALL(access));
Allow(SYSCALL(unlink));
Allow(SYSCALL(fsync));
Allow(SYSCALL(msync));
/* Should remove all of the following in the future, if possible */
ALLOW_SYSCALL(getpriority),
ALLOW_SYSCALL(sched_get_priority_min),
ALLOW_SYSCALL(sched_get_priority_max),
ALLOW_SYSCALL(setpriority),
Allow(SYSCALL(getpriority));
Allow(SYSCALL(sched_get_priority_min));
Allow(SYSCALL(sched_get_priority_max));
Allow(SYSCALL(setpriority));
// rt_sigprocmask is passed the sigset_t size. On older archs,
// sigprocmask is a compatibility shim that assumes the pre-RT size.
#if SYSCALL_EXISTS(sigprocmask)
ALLOW_SYSCALL(sigprocmask),
Allow(SYSCALL(sigprocmask));
#endif
ALLOW_SYSCALL(rt_sigprocmask),
Allow(SYSCALL(rt_sigprocmask));
// Used by profiler. Also used for raise(), which causes problems
// with Android KitKat abort(); see bug 1004832.
ALLOW_SYSCALL(tgkill),
Allow(SYSCALL(tgkill));
/* B2G specific low-frequency syscalls */
#ifdef MOZ_WIDGET_GONK
#if !SYSCALL_EXISTS(socketcall)
ALLOW_SYSCALL(sendto),
ALLOW_SYSCALL(recvfrom),
Allow(SYSCALL(sendto));
Allow(SYSCALL(recvfrom));
#endif
ALLOW_SYSCALL_LARGEFILE(getdents, getdents64),
ALLOW_SYSCALL(epoll_ctl),
ALLOW_SYSCALL(sched_yield),
ALLOW_SYSCALL(sched_getscheduler),
ALLOW_SYSCALL(sched_setscheduler),
ALLOW_SYSCALL(sigaltstack),
Allow(SYSCALL_LARGEFILE(getdents, getdents64));
Allow(SYSCALL(epoll_ctl));
Allow(SYSCALL(sched_yield));
Allow(SYSCALL(sched_getscheduler));
Allow(SYSCALL(sched_setscheduler));
Allow(SYSCALL(sigaltstack));
#endif
/* Always last and always OK calls */
/* Architecture-specific very infrequently used syscalls */
#if SYSCALL_EXISTS(sigaction)
ALLOW_SYSCALL(sigaction),
Allow(SYSCALL(sigaction));
#endif
ALLOW_SYSCALL(rt_sigaction),
#ifdef ALLOW_ARM_SYSCALL
ALLOW_ARM_SYSCALL(breakpoint),
ALLOW_ARM_SYSCALL(cacheflush),
ALLOW_ARM_SYSCALL(usr26),
ALLOW_ARM_SYSCALL(usr32),
ALLOW_ARM_SYSCALL(set_tls),
Allow(SYSCALL(rt_sigaction));
#ifdef ARM_SYSCALL
Allow(ARM_SYSCALL(breakpoint));
Allow(ARM_SYSCALL(cacheflush));
Allow(ARM_SYSCALL(usr26));
Allow(ARM_SYSCALL(usr32));
Allow(ARM_SYSCALL(set_tls));
#endif
/* restart_syscall is called internally, generally when debugging */
ALLOW_SYSCALL(restart_syscall),
Allow(SYSCALL(restart_syscall));
/* linux desktop is not as performance critical as B2G */
/* we can place desktop syscalls at the end */
#ifndef MOZ_WIDGET_GONK
ALLOW_SYSCALL(stat),
ALLOW_SYSCALL(getdents),
ALLOW_SYSCALL(lstat),
ALLOW_SYSCALL(mmap),
ALLOW_SYSCALL(openat),
ALLOW_SYSCALL(fcntl),
ALLOW_SYSCALL(fstat),
ALLOW_SYSCALL(readlink),
ALLOW_SYSCALL(getsockname),
ALLOW_SYSCALL(getuid),
ALLOW_SYSCALL(geteuid),
ALLOW_SYSCALL(mkdir),
ALLOW_SYSCALL(getcwd),
ALLOW_SYSCALL(readahead),
ALLOW_SYSCALL(pread64),
ALLOW_SYSCALL(statfs),
ALLOW_SYSCALL(pipe),
ALLOW_SYSCALL(getrlimit),
ALLOW_SYSCALL(shutdown),
ALLOW_SYSCALL(getpeername),
ALLOW_SYSCALL(eventfd2),
ALLOW_SYSCALL(clock_getres),
ALLOW_SYSCALL(sysinfo),
ALLOW_SYSCALL(getresuid),
ALLOW_SYSCALL(umask),
ALLOW_SYSCALL(getresgid),
ALLOW_SYSCALL(poll),
ALLOW_SYSCALL(getegid),
ALLOW_SYSCALL(inotify_init1),
ALLOW_SYSCALL(wait4),
ALLOW_SYSCALL(shmctl),
ALLOW_SYSCALL(set_robust_list),
ALLOW_SYSCALL(rmdir),
ALLOW_SYSCALL(recvfrom),
ALLOW_SYSCALL(shmdt),
ALLOW_SYSCALL(pipe2),
ALLOW_SYSCALL(setsockopt),
ALLOW_SYSCALL(shmat),
ALLOW_SYSCALL(set_tid_address),
ALLOW_SYSCALL(inotify_add_watch),
ALLOW_SYSCALL(rt_sigprocmask),
ALLOW_SYSCALL(shmget),
ALLOW_SYSCALL(getgid),
ALLOW_SYSCALL(utime),
ALLOW_SYSCALL(arch_prctl),
ALLOW_SYSCALL(sched_getaffinity),
Allow(SYSCALL(stat));
Allow(SYSCALL(getdents));
Allow(SYSCALL(lstat));
Allow(SYSCALL(mmap));
Allow(SYSCALL(openat));
Allow(SYSCALL(fcntl));
Allow(SYSCALL(fstat));
Allow(SYSCALL(readlink));
Allow(SYSCALL(getsockname));
Allow(SYSCALL(getuid));
Allow(SYSCALL(geteuid));
Allow(SYSCALL(mkdir));
Allow(SYSCALL(getcwd));
Allow(SYSCALL(readahead));
Allow(SYSCALL(pread64));
Allow(SYSCALL(statfs));
Allow(SYSCALL(pipe));
Allow(SYSCALL(getrlimit));
Allow(SYSCALL(shutdown));
Allow(SYSCALL(getpeername));
Allow(SYSCALL(eventfd2));
Allow(SYSCALL(clock_getres));
Allow(SYSCALL(sysinfo));
Allow(SYSCALL(getresuid));
Allow(SYSCALL(umask));
Allow(SYSCALL(getresgid));
Allow(SYSCALL(poll));
Allow(SYSCALL(getegid));
Allow(SYSCALL(inotify_init1));
Allow(SYSCALL(wait4));
Allow(SYSCALL(shmctl));
Allow(SYSCALL(set_robust_list));
Allow(SYSCALL(rmdir));
Allow(SYSCALL(recvfrom));
Allow(SYSCALL(shmdt));
Allow(SYSCALL(pipe2));
Allow(SYSCALL(setsockopt));
Allow(SYSCALL(shmat));
Allow(SYSCALL(set_tid_address));
Allow(SYSCALL(inotify_add_watch));
Allow(SYSCALL(rt_sigprocmask));
Allow(SYSCALL(shmget));
Allow(SYSCALL(getgid));
Allow(SYSCALL(utime));
Allow(SYSCALL(arch_prctl));
Allow(SYSCALL(sched_getaffinity));
/* We should remove all of the following in the future (possibly even more) */
ALLOW_SYSCALL(socket),
ALLOW_SYSCALL(chmod),
ALLOW_SYSCALL(execve),
ALLOW_SYSCALL(rename),
ALLOW_SYSCALL(symlink),
ALLOW_SYSCALL(connect),
ALLOW_SYSCALL(quotactl),
ALLOW_SYSCALL(kill),
ALLOW_SYSCALL(sendto),
Allow(SYSCALL(socket));
Allow(SYSCALL(chmod));
Allow(SYSCALL(execve));
Allow(SYSCALL(rename));
Allow(SYSCALL(symlink));
Allow(SYSCALL(connect));
Allow(SYSCALL(quotactl));
Allow(SYSCALL(kill));
Allow(SYSCALL(sendto));
#endif
/* nsSystemInfo uses uname (and we cache an instance, so */
/* the info remains present even if we block the syscall) */
ALLOW_SYSCALL(uname),
ALLOW_SYSCALL(exit_group),
ALLOW_SYSCALL(exit),
#ifdef MOZ_CONTENT_SANDBOX_REPORTER
TRAP_PROCESS,
#else
KILL_PROCESS,
#endif
};
static struct sock_fprog seccomp_prog = {
(unsigned short)MOZ_ARRAY_LENGTH(seccomp_filter),
seccomp_filter,
};
const sock_fprog*
GetSandboxFilter()
{
return &seccomp_prog;
Allow(SYSCALL(uname));
Allow(SYSCALL(exit_group));
Allow(SYSCALL(exit));
}
}

View File

@ -8,11 +8,20 @@
#define mozilla_SandboxFilter_h
struct sock_fprog;
struct sock_filter;
namespace mozilla {
const sock_fprog* GetSandboxFilter();
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, bool aVerbose = false);
~SandboxFilter();
};
}
#endif

View File

@ -11,10 +11,15 @@ EXPORTS.mozilla += [
]
SOURCES += [
'../chromium/sandbox/linux/seccomp-bpf/basicblock.cc',
'../chromium/sandbox/linux/seccomp-bpf/codegen.cc',
'Sandbox.cpp',
'SandboxAssembler.cpp',
'SandboxFilter.cpp',
]
LOCAL_INCLUDES += ['/security/sandbox/chromium']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'