зеркало из https://github.com/mozilla/gecko-dev.git
Bug 920372 - Use Chromium seccomp-bpf compiler to dynamically build sandbox program. r=kang
This commit is contained in:
Родитель
9e94aea459
Коммит
ebb89f61f4
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
Загрузка…
Ссылка в новой задаче