mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 920372 - Use Chromium seccomp-bpf compiler to dynamically build sandbox program. r=kang
This commit is contained in:
parent
3b103d307f
commit
3a308504da
@ -47,6 +47,9 @@
|
|||||||
#include "prlog.h"
|
#include "prlog.h"
|
||||||
#include "prenv.h"
|
#include "prenv.h"
|
||||||
|
|
||||||
|
// See definition of SandboxDie, below.
|
||||||
|
#include "sandbox/linux/seccomp-bpf/die.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
#if defined(ANDROID)
|
#if defined(ANDROID)
|
||||||
#define LOG_ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "Sandbox", ## args)
|
#define LOG_ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "Sandbox", ## args)
|
||||||
@ -206,7 +209,7 @@ InstallSyscallReporter(void)
|
|||||||
* @see sock_fprog (the seccomp_prog).
|
* @see sock_fprog (the seccomp_prog).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
InstallSyscallFilter(void)
|
InstallSyscallFilter(const sock_fprog *prog)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_DMD
|
#ifdef MOZ_DMD
|
||||||
char* e = PR_GetEnv("DMD");
|
char* e = PR_GetEnv("DMD");
|
||||||
@ -221,9 +224,7 @@ InstallSyscallFilter(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sock_fprog *filter = GetSandboxFilter();
|
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)prog, 0, 0)) {
|
||||||
|
|
||||||
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (unsigned long)filter, 0, 0)) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -235,6 +236,8 @@ static mozilla::Atomic<int> sSetSandboxDone;
|
|||||||
// about:memory has the first 3 RT signals. (We should allocate
|
// about:memory has the first 3 RT signals. (We should allocate
|
||||||
// signals centrally instead of hard-coding them like this.)
|
// signals centrally instead of hard-coding them like this.)
|
||||||
static const int sSetSandboxSignum = SIGRTMIN + 3;
|
static const int sSetSandboxSignum = SIGRTMIN + 3;
|
||||||
|
// Pass the filter itself through a global.
|
||||||
|
static const sock_fprog *sSetSandboxFilter;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
SetThreadSandbox()
|
SetThreadSandbox()
|
||||||
@ -243,7 +246,7 @@ SetThreadSandbox()
|
|||||||
|
|
||||||
if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
|
if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
|
||||||
prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
|
prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
|
||||||
if (InstallSyscallFilter() == 0) {
|
if (InstallSyscallFilter(sSetSandboxFilter) == 0) {
|
||||||
didAnything = true;
|
didAnything = true;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -277,6 +280,8 @@ BroadcastSetThreadSandbox()
|
|||||||
pid_t pid, tid;
|
pid_t pid, tid;
|
||||||
DIR *taskdp;
|
DIR *taskdp;
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
|
SandboxFilter filter(&sSetSandboxFilter,
|
||||||
|
PR_GetEnv("MOZ_CONTENT_SANDBOX_VERBOSE"));
|
||||||
|
|
||||||
static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
|
static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
|
||||||
"mozilla::Atomic<int> isn't represented by an int");
|
"mozilla::Atomic<int> isn't represented by an int");
|
||||||
@ -425,3 +430,33 @@ SetCurrentProcessSandbox()
|
|||||||
|
|
||||||
} // namespace mozilla
|
} // 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
|
||||||
|
150
security/sandbox/linux/SandboxAssembler.cpp
Normal file
150
security/sandbox/linux/SandboxAssembler.cpp
Normal 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
|
97
security/sandbox/linux/SandboxAssembler.h
Normal file
97
security/sandbox/linux/SandboxAssembler.h
Normal 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
|
@ -5,30 +5,76 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "SandboxFilter.h"
|
#include "SandboxFilter.h"
|
||||||
|
#include "SandboxAssembler.h"
|
||||||
|
|
||||||
#include "linux_seccomp.h"
|
#include "linux_seccomp.h"
|
||||||
#include "linux_syscalls.h"
|
#include "linux_syscalls.h"
|
||||||
|
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
|
#include "mozilla/NullPtr.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
namespace mozilla {
|
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[] = {
|
SandboxFilter::SandboxFilter(const sock_fprog** aStored, bool aVerbose)
|
||||||
VALIDATE_ARCHITECTURE,
|
: mStored(aStored)
|
||||||
EXAMINE_SYSCALL,
|
{
|
||||||
|
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
|
// Some architectures went through a transition from 32-bit to
|
||||||
// 64-bit off_t and had to version all the syscalls that referenced
|
// 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
|
// it; others (newer and/or 64-bit ones) didn't. Adjust the
|
||||||
// conditional as needed.
|
// conditional as needed.
|
||||||
#if SYSCALL_EXISTS(stat64)
|
#if SYSCALL_EXISTS(stat64)
|
||||||
#define ALLOW_SYSCALL_LARGEFILE(plain, versioned) ALLOW_SYSCALL(versioned)
|
#define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(versioned)
|
||||||
#else
|
#else
|
||||||
#define ALLOW_SYSCALL_LARGEFILE(plain, versioned) ALLOW_SYSCALL(plain)
|
#define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(plain)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Most used system calls should be at the top of the whitelist
|
/* 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.
|
* '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
|
// FIXME, bug 920372: i386 multiplexes all the socket-related
|
||||||
// interfaces into a single syscall. We should check the selector.
|
// interfaces into a single syscall. We should check the selector.
|
||||||
#if SYSCALL_EXISTS(socketcall)
|
#if SYSCALL_EXISTS(socketcall)
|
||||||
ALLOW_SYSCALL(socketcall),
|
Allow(SYSCALL(socketcall));
|
||||||
#else
|
#else
|
||||||
ALLOW_SYSCALL(recvmsg),
|
Allow(SYSCALL(recvmsg));
|
||||||
ALLOW_SYSCALL(sendmsg),
|
Allow(SYSCALL(sendmsg));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// mmap2 is a little different from most off_t users, because it's
|
// 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
|
// 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.
|
// arch) -- and the workaround, mmap2, passes a page offset instead.
|
||||||
#if SYSCALL_EXISTS(mmap2)
|
#if SYSCALL_EXISTS(mmap2)
|
||||||
ALLOW_SYSCALL(mmap2),
|
Allow(SYSCALL(mmap2));
|
||||||
#else
|
#else
|
||||||
ALLOW_SYSCALL(mmap),
|
Allow(SYSCALL(mmap));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* B2G specific high-frequency syscalls */
|
/* B2G specific high-frequency syscalls */
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
ALLOW_SYSCALL(clock_gettime),
|
Allow(SYSCALL(clock_gettime));
|
||||||
ALLOW_SYSCALL(epoll_wait),
|
Allow(SYSCALL(epoll_wait));
|
||||||
ALLOW_SYSCALL(gettimeofday),
|
Allow(SYSCALL(gettimeofday));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL(read),
|
Allow(SYSCALL(read));
|
||||||
ALLOW_SYSCALL(write),
|
Allow(SYSCALL(write));
|
||||||
// 32-bit lseek is used, at least on Android, to implement ANSI fseek.
|
// 32-bit lseek is used, at least on Android, to implement ANSI fseek.
|
||||||
#if SYSCALL_EXISTS(_llseek)
|
#if SYSCALL_EXISTS(_llseek)
|
||||||
ALLOW_SYSCALL(_llseek),
|
Allow(SYSCALL(_llseek));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL(lseek),
|
Allow(SYSCALL(lseek));
|
||||||
// Android also uses 32-bit ftruncate.
|
// Android also uses 32-bit ftruncate.
|
||||||
ALLOW_SYSCALL(ftruncate),
|
Allow(SYSCALL(ftruncate));
|
||||||
#if SYSCALL_EXISTS(ftruncate64)
|
#if SYSCALL_EXISTS(ftruncate64)
|
||||||
ALLOW_SYSCALL(ftruncate64),
|
Allow(SYSCALL(ftruncate64));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ioctl() is for GL. Remove when GL proxy is implemented.
|
/* ioctl() is for GL. Remove when GL proxy is implemented.
|
||||||
* Additionally ioctl() might be a place where we want to have
|
* Additionally ioctl() might be a place where we want to have
|
||||||
* argument filtering */
|
* argument filtering */
|
||||||
ALLOW_SYSCALL(ioctl),
|
Allow(SYSCALL(ioctl));
|
||||||
ALLOW_SYSCALL(close),
|
Allow(SYSCALL(close));
|
||||||
ALLOW_SYSCALL(munmap),
|
Allow(SYSCALL(munmap));
|
||||||
ALLOW_SYSCALL(mprotect),
|
Allow(SYSCALL(mprotect));
|
||||||
ALLOW_SYSCALL(writev),
|
Allow(SYSCALL(writev));
|
||||||
ALLOW_SYSCALL(clone),
|
Allow(SYSCALL(clone));
|
||||||
ALLOW_SYSCALL(brk),
|
Allow(SYSCALL(brk));
|
||||||
#if SYSCALL_EXISTS(set_thread_area)
|
#if SYSCALL_EXISTS(set_thread_area)
|
||||||
ALLOW_SYSCALL(set_thread_area),
|
Allow(SYSCALL(set_thread_area));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ALLOW_SYSCALL(getpid),
|
Allow(SYSCALL(getpid));
|
||||||
ALLOW_SYSCALL(gettid),
|
Allow(SYSCALL(gettid));
|
||||||
ALLOW_SYSCALL(getrusage),
|
Allow(SYSCALL(getrusage));
|
||||||
ALLOW_SYSCALL(madvise),
|
Allow(SYSCALL(madvise));
|
||||||
ALLOW_SYSCALL(dup),
|
Allow(SYSCALL(dup));
|
||||||
ALLOW_SYSCALL(nanosleep),
|
Allow(SYSCALL(nanosleep));
|
||||||
ALLOW_SYSCALL(poll),
|
Allow(SYSCALL(poll));
|
||||||
// select()'s arguments used to be passed by pointer as a struct.
|
// select()'s arguments used to be passed by pointer as a struct.
|
||||||
#if SYSCALL_EXISTS(_newselect)
|
#if SYSCALL_EXISTS(_newselect)
|
||||||
ALLOW_SYSCALL(_newselect),
|
Allow(SYSCALL(_newselect));
|
||||||
#else
|
#else
|
||||||
ALLOW_SYSCALL(select),
|
Allow(SYSCALL(select));
|
||||||
#endif
|
#endif
|
||||||
// Some archs used to have 16-bit uid/gid instead of 32-bit.
|
// Some archs used to have 16-bit uid/gid instead of 32-bit.
|
||||||
#if SYSCALL_EXISTS(getuid32)
|
#if SYSCALL_EXISTS(getuid32)
|
||||||
ALLOW_SYSCALL(getuid32),
|
Allow(SYSCALL(getuid32));
|
||||||
ALLOW_SYSCALL(geteuid32),
|
Allow(SYSCALL(geteuid32));
|
||||||
#else
|
#else
|
||||||
ALLOW_SYSCALL(getuid),
|
Allow(SYSCALL(getuid));
|
||||||
ALLOW_SYSCALL(geteuid),
|
Allow(SYSCALL(geteuid));
|
||||||
#endif
|
#endif
|
||||||
// Some newer archs (e.g., x64 and x32) have only rt_sigreturn, but
|
// Some newer archs (e.g., x64 and x32) have only rt_sigreturn, but
|
||||||
// ARM has and uses both syscalls -- rt_sigreturn for SA_SIGINFO
|
// ARM has and uses both syscalls -- rt_sigreturn for SA_SIGINFO
|
||||||
// handlers and classic sigreturn otherwise.
|
// handlers and classic sigreturn otherwise.
|
||||||
#if SYSCALL_EXISTS(sigreturn)
|
#if SYSCALL_EXISTS(sigreturn)
|
||||||
ALLOW_SYSCALL(sigreturn),
|
Allow(SYSCALL(sigreturn));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL(rt_sigreturn),
|
Allow(SYSCALL(rt_sigreturn));
|
||||||
ALLOW_SYSCALL_LARGEFILE(fcntl, fcntl64),
|
Allow(SYSCALL_LARGEFILE(fcntl, fcntl64));
|
||||||
|
|
||||||
/* Must remove all of the following in the future, when no longer used */
|
/* Must remove all of the following in the future, when no longer used */
|
||||||
/* open() is for some legacy APIs such as font loading. */
|
/* open() is for some legacy APIs such as font loading. */
|
||||||
/* See bug 906996 for removing unlink(). */
|
/* See bug 906996 for removing unlink(). */
|
||||||
ALLOW_SYSCALL_LARGEFILE(fstat, fstat64),
|
Allow(SYSCALL_LARGEFILE(fstat, fstat64));
|
||||||
ALLOW_SYSCALL_LARGEFILE(stat, stat64),
|
Allow(SYSCALL_LARGEFILE(stat, stat64));
|
||||||
ALLOW_SYSCALL_LARGEFILE(lstat, lstat64),
|
Allow(SYSCALL_LARGEFILE(lstat, lstat64));
|
||||||
// FIXME, bug 920372: see above.
|
// FIXME, bug 920372: see above.
|
||||||
#if !SYSCALL_EXISTS(socketcall)
|
#if !SYSCALL_EXISTS(socketcall)
|
||||||
ALLOW_SYSCALL(socketpair),
|
Allow(SYSCALL(socketpair));
|
||||||
DENY_SYSCALL(socket, EACCES),
|
Deny(EACCES, SYSCALL(socket));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL(open),
|
Allow(SYSCALL(open));
|
||||||
ALLOW_SYSCALL(readlink), /* Workaround for bug 964455 */
|
Allow(SYSCALL(readlink)); /* Workaround for bug 964455 */
|
||||||
ALLOW_SYSCALL(prctl),
|
Allow(SYSCALL(prctl));
|
||||||
ALLOW_SYSCALL(access),
|
Allow(SYSCALL(access));
|
||||||
ALLOW_SYSCALL(unlink),
|
Allow(SYSCALL(unlink));
|
||||||
ALLOW_SYSCALL(fsync),
|
Allow(SYSCALL(fsync));
|
||||||
ALLOW_SYSCALL(msync),
|
Allow(SYSCALL(msync));
|
||||||
|
|
||||||
/* Should remove all of the following in the future, if possible */
|
/* Should remove all of the following in the future, if possible */
|
||||||
ALLOW_SYSCALL(getpriority),
|
Allow(SYSCALL(getpriority));
|
||||||
ALLOW_SYSCALL(sched_get_priority_min),
|
Allow(SYSCALL(sched_get_priority_min));
|
||||||
ALLOW_SYSCALL(sched_get_priority_max),
|
Allow(SYSCALL(sched_get_priority_max));
|
||||||
ALLOW_SYSCALL(setpriority),
|
Allow(SYSCALL(setpriority));
|
||||||
// rt_sigprocmask is passed the sigset_t size. On older archs,
|
// rt_sigprocmask is passed the sigset_t size. On older archs,
|
||||||
// sigprocmask is a compatibility shim that assumes the pre-RT size.
|
// sigprocmask is a compatibility shim that assumes the pre-RT size.
|
||||||
#if SYSCALL_EXISTS(sigprocmask)
|
#if SYSCALL_EXISTS(sigprocmask)
|
||||||
ALLOW_SYSCALL(sigprocmask),
|
Allow(SYSCALL(sigprocmask));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL(rt_sigprocmask),
|
Allow(SYSCALL(rt_sigprocmask));
|
||||||
|
|
||||||
// Used by profiler. Also used for raise(), which causes problems
|
// Used by profiler. Also used for raise(), which causes problems
|
||||||
// with Android KitKat abort(); see bug 1004832.
|
// with Android KitKat abort(); see bug 1004832.
|
||||||
ALLOW_SYSCALL(tgkill),
|
Allow(SYSCALL(tgkill));
|
||||||
|
|
||||||
/* B2G specific low-frequency syscalls */
|
/* B2G specific low-frequency syscalls */
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
#if !SYSCALL_EXISTS(socketcall)
|
#if !SYSCALL_EXISTS(socketcall)
|
||||||
ALLOW_SYSCALL(sendto),
|
Allow(SYSCALL(sendto));
|
||||||
ALLOW_SYSCALL(recvfrom),
|
Allow(SYSCALL(recvfrom));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL_LARGEFILE(getdents, getdents64),
|
Allow(SYSCALL_LARGEFILE(getdents, getdents64));
|
||||||
ALLOW_SYSCALL(epoll_ctl),
|
Allow(SYSCALL(epoll_ctl));
|
||||||
ALLOW_SYSCALL(sched_yield),
|
Allow(SYSCALL(sched_yield));
|
||||||
ALLOW_SYSCALL(sched_getscheduler),
|
Allow(SYSCALL(sched_getscheduler));
|
||||||
ALLOW_SYSCALL(sched_setscheduler),
|
Allow(SYSCALL(sched_setscheduler));
|
||||||
ALLOW_SYSCALL(sigaltstack),
|
Allow(SYSCALL(sigaltstack));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Always last and always OK calls */
|
/* Always last and always OK calls */
|
||||||
/* Architecture-specific very infrequently used syscalls */
|
/* Architecture-specific very infrequently used syscalls */
|
||||||
#if SYSCALL_EXISTS(sigaction)
|
#if SYSCALL_EXISTS(sigaction)
|
||||||
ALLOW_SYSCALL(sigaction),
|
Allow(SYSCALL(sigaction));
|
||||||
#endif
|
#endif
|
||||||
ALLOW_SYSCALL(rt_sigaction),
|
Allow(SYSCALL(rt_sigaction));
|
||||||
#ifdef ALLOW_ARM_SYSCALL
|
#ifdef ARM_SYSCALL
|
||||||
ALLOW_ARM_SYSCALL(breakpoint),
|
Allow(ARM_SYSCALL(breakpoint));
|
||||||
ALLOW_ARM_SYSCALL(cacheflush),
|
Allow(ARM_SYSCALL(cacheflush));
|
||||||
ALLOW_ARM_SYSCALL(usr26),
|
Allow(ARM_SYSCALL(usr26));
|
||||||
ALLOW_ARM_SYSCALL(usr32),
|
Allow(ARM_SYSCALL(usr32));
|
||||||
ALLOW_ARM_SYSCALL(set_tls),
|
Allow(ARM_SYSCALL(set_tls));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* restart_syscall is called internally, generally when debugging */
|
/* 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 */
|
/* linux desktop is not as performance critical as B2G */
|
||||||
/* we can place desktop syscalls at the end */
|
/* we can place desktop syscalls at the end */
|
||||||
#ifndef MOZ_WIDGET_GONK
|
#ifndef MOZ_WIDGET_GONK
|
||||||
ALLOW_SYSCALL(stat),
|
Allow(SYSCALL(stat));
|
||||||
ALLOW_SYSCALL(getdents),
|
Allow(SYSCALL(getdents));
|
||||||
ALLOW_SYSCALL(lstat),
|
Allow(SYSCALL(lstat));
|
||||||
ALLOW_SYSCALL(mmap),
|
Allow(SYSCALL(mmap));
|
||||||
ALLOW_SYSCALL(openat),
|
Allow(SYSCALL(openat));
|
||||||
ALLOW_SYSCALL(fcntl),
|
Allow(SYSCALL(fcntl));
|
||||||
ALLOW_SYSCALL(fstat),
|
Allow(SYSCALL(fstat));
|
||||||
ALLOW_SYSCALL(readlink),
|
Allow(SYSCALL(readlink));
|
||||||
ALLOW_SYSCALL(getsockname),
|
Allow(SYSCALL(getsockname));
|
||||||
ALLOW_SYSCALL(getuid),
|
Allow(SYSCALL(getuid));
|
||||||
ALLOW_SYSCALL(geteuid),
|
Allow(SYSCALL(geteuid));
|
||||||
ALLOW_SYSCALL(mkdir),
|
Allow(SYSCALL(mkdir));
|
||||||
ALLOW_SYSCALL(getcwd),
|
Allow(SYSCALL(getcwd));
|
||||||
ALLOW_SYSCALL(readahead),
|
Allow(SYSCALL(readahead));
|
||||||
ALLOW_SYSCALL(pread64),
|
Allow(SYSCALL(pread64));
|
||||||
ALLOW_SYSCALL(statfs),
|
Allow(SYSCALL(statfs));
|
||||||
ALLOW_SYSCALL(pipe),
|
Allow(SYSCALL(pipe));
|
||||||
ALLOW_SYSCALL(getrlimit),
|
Allow(SYSCALL(getrlimit));
|
||||||
ALLOW_SYSCALL(shutdown),
|
Allow(SYSCALL(shutdown));
|
||||||
ALLOW_SYSCALL(getpeername),
|
Allow(SYSCALL(getpeername));
|
||||||
ALLOW_SYSCALL(eventfd2),
|
Allow(SYSCALL(eventfd2));
|
||||||
ALLOW_SYSCALL(clock_getres),
|
Allow(SYSCALL(clock_getres));
|
||||||
ALLOW_SYSCALL(sysinfo),
|
Allow(SYSCALL(sysinfo));
|
||||||
ALLOW_SYSCALL(getresuid),
|
Allow(SYSCALL(getresuid));
|
||||||
ALLOW_SYSCALL(umask),
|
Allow(SYSCALL(umask));
|
||||||
ALLOW_SYSCALL(getresgid),
|
Allow(SYSCALL(getresgid));
|
||||||
ALLOW_SYSCALL(poll),
|
Allow(SYSCALL(poll));
|
||||||
ALLOW_SYSCALL(getegid),
|
Allow(SYSCALL(getegid));
|
||||||
ALLOW_SYSCALL(inotify_init1),
|
Allow(SYSCALL(inotify_init1));
|
||||||
ALLOW_SYSCALL(wait4),
|
Allow(SYSCALL(wait4));
|
||||||
ALLOW_SYSCALL(shmctl),
|
Allow(SYSCALL(shmctl));
|
||||||
ALLOW_SYSCALL(set_robust_list),
|
Allow(SYSCALL(set_robust_list));
|
||||||
ALLOW_SYSCALL(rmdir),
|
Allow(SYSCALL(rmdir));
|
||||||
ALLOW_SYSCALL(recvfrom),
|
Allow(SYSCALL(recvfrom));
|
||||||
ALLOW_SYSCALL(shmdt),
|
Allow(SYSCALL(shmdt));
|
||||||
ALLOW_SYSCALL(pipe2),
|
Allow(SYSCALL(pipe2));
|
||||||
ALLOW_SYSCALL(setsockopt),
|
Allow(SYSCALL(setsockopt));
|
||||||
ALLOW_SYSCALL(shmat),
|
Allow(SYSCALL(shmat));
|
||||||
ALLOW_SYSCALL(set_tid_address),
|
Allow(SYSCALL(set_tid_address));
|
||||||
ALLOW_SYSCALL(inotify_add_watch),
|
Allow(SYSCALL(inotify_add_watch));
|
||||||
ALLOW_SYSCALL(rt_sigprocmask),
|
Allow(SYSCALL(rt_sigprocmask));
|
||||||
ALLOW_SYSCALL(shmget),
|
Allow(SYSCALL(shmget));
|
||||||
ALLOW_SYSCALL(getgid),
|
Allow(SYSCALL(getgid));
|
||||||
ALLOW_SYSCALL(utime),
|
Allow(SYSCALL(utime));
|
||||||
ALLOW_SYSCALL(arch_prctl),
|
Allow(SYSCALL(arch_prctl));
|
||||||
ALLOW_SYSCALL(sched_getaffinity),
|
Allow(SYSCALL(sched_getaffinity));
|
||||||
/* We should remove all of the following in the future (possibly even more) */
|
/* We should remove all of the following in the future (possibly even more) */
|
||||||
ALLOW_SYSCALL(socket),
|
Allow(SYSCALL(socket));
|
||||||
ALLOW_SYSCALL(chmod),
|
Allow(SYSCALL(chmod));
|
||||||
ALLOW_SYSCALL(execve),
|
Allow(SYSCALL(execve));
|
||||||
ALLOW_SYSCALL(rename),
|
Allow(SYSCALL(rename));
|
||||||
ALLOW_SYSCALL(symlink),
|
Allow(SYSCALL(symlink));
|
||||||
ALLOW_SYSCALL(connect),
|
Allow(SYSCALL(connect));
|
||||||
ALLOW_SYSCALL(quotactl),
|
Allow(SYSCALL(quotactl));
|
||||||
ALLOW_SYSCALL(kill),
|
Allow(SYSCALL(kill));
|
||||||
ALLOW_SYSCALL(sendto),
|
Allow(SYSCALL(sendto));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* nsSystemInfo uses uname (and we cache an instance, so */
|
/* nsSystemInfo uses uname (and we cache an instance, so */
|
||||||
/* the info remains present even if we block the syscall) */
|
/* the info remains present even if we block the syscall) */
|
||||||
ALLOW_SYSCALL(uname),
|
Allow(SYSCALL(uname));
|
||||||
ALLOW_SYSCALL(exit_group),
|
Allow(SYSCALL(exit_group));
|
||||||
ALLOW_SYSCALL(exit),
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,20 @@
|
|||||||
#define mozilla_SandboxFilter_h
|
#define mozilla_SandboxFilter_h
|
||||||
|
|
||||||
struct sock_fprog;
|
struct sock_fprog;
|
||||||
|
struct sock_filter;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
class SandboxFilter {
|
||||||
const sock_fprog* GetSandboxFilter();
|
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
|
#endif
|
||||||
|
@ -11,10 +11,15 @@ EXPORTS.mozilla += [
|
|||||||
]
|
]
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
|
'../chromium/sandbox/linux/seccomp-bpf/basicblock.cc',
|
||||||
|
'../chromium/sandbox/linux/seccomp-bpf/codegen.cc',
|
||||||
'Sandbox.cpp',
|
'Sandbox.cpp',
|
||||||
|
'SandboxAssembler.cpp',
|
||||||
'SandboxFilter.cpp',
|
'SandboxFilter.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
LOCAL_INCLUDES += ['/security/sandbox/chromium']
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
Loading…
Reference in New Issue
Block a user