Merge from Chromium at DEPS revision 278205
This commit was generated by merge_to_master.py.
Change-Id: I23f1e7ea8c154ba72e7fb594436216f861f868ab
diff --git a/sandbox/BUILD.gn b/sandbox/BUILD.gn
index 71de29f..e3a8b62 100644
--- a/sandbox/BUILD.gn
+++ b/sandbox/BUILD.gn
@@ -6,9 +6,8 @@
group("sandbox") {
if (is_win) {
deps = [ "//sandbox/win:sandbox" ]
- # TODO(GYP)
- #} else if (is_mac) {
- # deps = [ "//sandbox/mac:sandbox" ]
+ } else if (is_mac) {
+ deps = [ "//sandbox/mac:sandbox" ]
} else if (is_linux || is_android) {
deps = [ "//sandbox/linux:sandbox" ]
}
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index 53518b8..6235248 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -216,6 +216,13 @@
'include_dirs': [
'../..',
],
+ # Do not use any sanitizer tools with this binary. http://crbug.com/382766
+ 'cflags/': [
+ ['exclude', '-fsanitize'],
+ ],
+ 'ldflags/': [
+ ['exclude', '-fsanitize'],
+ ],
},
{ 'target_name': 'sandbox_services',
'type': '<(component)',
diff --git a/sandbox/linux/seccomp-bpf/codegen.cc b/sandbox/linux/seccomp-bpf/codegen.cc
index 211e659..c90bffc 100644
--- a/sandbox/linux/seccomp-bpf/codegen.cc
+++ b/sandbox/linux/seccomp-bpf/codegen.cc
@@ -106,6 +106,8 @@
fprintf(stderr, "Trap #%d\n", iter->k & SECCOMP_RET_DATA);
} else if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) {
fprintf(stderr, "errno = %d\n", iter->k & SECCOMP_RET_DATA);
+ } else if ((iter->k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE) {
+ fprintf(stderr, "Trace #%d\n", iter->k & SECCOMP_RET_DATA);
} else if (iter->k == SECCOMP_RET_ALLOW) {
fprintf(stderr, "Allowed\n");
} else {
diff --git a/sandbox/linux/seccomp-bpf/die.cc b/sandbox/linux/seccomp-bpf/die.cc
index 533e2e9..e5bc7c9 100644
--- a/sandbox/linux/seccomp-bpf/die.cc
+++ b/sandbox/linux/seccomp-bpf/die.cc
@@ -22,7 +22,7 @@
// Especially, since we are dealing with system call filters. Continuing
// execution would be very bad in most cases where ExitGroup() gets called.
// So, we'll try a few other strategies too.
- SandboxSyscall(__NR_exit_group, 1);
+ Syscall::Call(__NR_exit_group, 1);
// We have no idea what our run-time environment looks like. So, signal
// handlers might or might not do the right thing. Try to reset settings
@@ -30,7 +30,7 @@
// succeeded in doing so. Nonetheless, triggering a fatal signal could help
// us terminate.
signal(SIGSEGV, SIG_DFL);
- SandboxSyscall(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0);
+ Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0);
if (*(volatile char*)0) {
}
@@ -40,7 +40,7 @@
// We in fact retry the system call inside of our loop so that it will
// stand out when somebody tries to diagnose the problem by using "strace".
for (;;) {
- SandboxSyscall(__NR_exit_group, 1);
+ Syscall::Call(__NR_exit_group, 1);
}
}
@@ -75,7 +75,7 @@
// No need to loop. Short write()s are unlikely and if they happen we
// probably prefer them over a loop that blocks.
ignore_result(
- HANDLE_EINTR(SandboxSyscall(__NR_write, 2, s.c_str(), s.length())));
+ HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length())));
}
}
diff --git a/sandbox/linux/seccomp-bpf/errorcode.cc b/sandbox/linux/seccomp-bpf/errorcode.cc
index 6484852..5a45e4c 100644
--- a/sandbox/linux/seccomp-bpf/errorcode.cc
+++ b/sandbox/linux/seccomp-bpf/errorcode.cc
@@ -18,6 +18,11 @@
error_type_ = ET_SIMPLE;
break;
default:
+ if ((err & ~SECCOMP_RET_DATA) == ERR_TRACE) {
+ err_ = SECCOMP_RET_TRACE + (err & SECCOMP_RET_DATA);
+ error_type_ = ET_SIMPLE;
+ break;
+ }
SANDBOX_DIE("Invalid use of ErrorCode object");
}
}
diff --git a/sandbox/linux/seccomp-bpf/errorcode.h b/sandbox/linux/seccomp-bpf/errorcode.h
index 04f22ae..2e51381 100644
--- a/sandbox/linux/seccomp-bpf/errorcode.h
+++ b/sandbox/linux/seccomp-bpf/errorcode.h
@@ -30,6 +30,12 @@
// "errno" (see below) value instead.
ERR_ALLOWED = 0x04000000,
+ // If the progress is being ptraced with PTRACE_O_TRACESECCOMP, then the
+ // tracer will be notified of a PTRACE_EVENT_SECCOMP and allowed to change
+ // or skip the system call. The lower 16 bits of err will be available to
+ // the tracer via PTRACE_GETEVENTMSG.
+ ERR_TRACE = 0x08000000,
+
// Deny the system call with a particular "errno" value.
// N.B.: It is also possible to return "0" here. That would normally
// indicate success, but it won't actually run the system call.
diff --git a/sandbox/linux/seccomp-bpf/errorcode_unittest.cc b/sandbox/linux/seccomp-bpf/errorcode_unittest.cc
index ef04a5f..f3b7748 100644
--- a/sandbox/linux/seccomp-bpf/errorcode_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/errorcode_unittest.cc
@@ -24,6 +24,17 @@
SandboxBPF sandbox;
ErrorCode e3 = sandbox.Trap(NULL, NULL);
SANDBOX_ASSERT((e3.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP);
+
+ uint16_t data = 0xdead;
+ ErrorCode e4(ErrorCode::ERR_TRACE + data);
+ SANDBOX_ASSERT(e4.err() == SECCOMP_RET_TRACE + data);
+}
+
+SANDBOX_DEATH_TEST(ErrorCode,
+ InvalidSeccompRetTrace,
+ DEATH_MESSAGE("Invalid use of ErrorCode object")) {
+ // Should die if the trace data does not fit in 16 bits.
+ ErrorCode e(ErrorCode::ERR_TRACE + (1 << 16));
}
SANDBOX_TEST(ErrorCode, Trap) {
diff --git a/sandbox/linux/seccomp-bpf/linux_seccomp.h b/sandbox/linux/seccomp-bpf/linux_seccomp.h
index 0de0259..270e11c 100644
--- a/sandbox/linux/seccomp-bpf/linux_seccomp.h
+++ b/sandbox/linux/seccomp-bpf/linux_seccomp.h
@@ -16,6 +16,14 @@
#include <asm/unistd.h>
#include <linux/filter.h>
+#include <sys/cdefs.h>
+// Old Bionic versions do not have sys/user.h. The if can be removed once we no
+// longer need to support these old Bionic versions.
+// All x86_64 builds use a new enough bionic to have sys/user.h.
+#if !defined(__BIONIC__) || defined(__x86_64__)
+#include <sys/user.h>
+#endif
+
// For audit.h
#ifndef EM_ARM
#define EM_ARM 40
@@ -124,6 +132,44 @@
#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \
8*(nr) + 0)
+
+#if defined(__BIONIC__)
+// Old Bionic versions don't have sys/user.h, so we just define regs_struct
+// directly. This can be removed once we no longer need to support these old
+// Bionic versions.
+struct regs_struct {
+ long int ebx;
+ long int ecx;
+ long int edx;
+ long int esi;
+ long int edi;
+ long int ebp;
+ long int eax;
+ long int xds;
+ long int xes;
+ long int xfs;
+ long int xgs;
+ long int orig_eax;
+ long int eip;
+ long int xcs;
+ long int eflags;
+ long int esp;
+ long int xss;
+};
+#else
+typedef user_regs_struct regs_struct;
+#endif
+
+#define SECCOMP_PT_RESULT(_regs) (_regs).eax
+#define SECCOMP_PT_SYSCALL(_regs) (_regs).orig_eax
+#define SECCOMP_PT_IP(_regs) (_regs).eip
+#define SECCOMP_PT_PARM1(_regs) (_regs).ebx
+#define SECCOMP_PT_PARM2(_regs) (_regs).ecx
+#define SECCOMP_PT_PARM3(_regs) (_regs).edx
+#define SECCOMP_PT_PARM4(_regs) (_regs).esi
+#define SECCOMP_PT_PARM5(_regs) (_regs).edi
+#define SECCOMP_PT_PARM6(_regs) (_regs).ebp
+
#elif defined(__x86_64__)
#define MIN_SYSCALL 0u
#define MAX_PUBLIC_SYSCALL 1024u
@@ -151,6 +197,17 @@
#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \
8*(nr) + 0)
+typedef user_regs_struct regs_struct;
+#define SECCOMP_PT_RESULT(_regs) (_regs).rax
+#define SECCOMP_PT_SYSCALL(_regs) (_regs).orig_rax
+#define SECCOMP_PT_IP(_regs) (_regs).rip
+#define SECCOMP_PT_PARM1(_regs) (_regs).rdi
+#define SECCOMP_PT_PARM2(_regs) (_regs).rsi
+#define SECCOMP_PT_PARM3(_regs) (_regs).rdx
+#define SECCOMP_PT_PARM4(_regs) (_regs).r10
+#define SECCOMP_PT_PARM5(_regs) (_regs).r8
+#define SECCOMP_PT_PARM6(_regs) (_regs).r9
+
#elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))
// ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|,
// and a "ghost syscall private to the kernel", cmpxchg,
@@ -189,6 +246,46 @@
#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \
8*(nr) + 0)
+#if defined(__BIONIC__)
+// Old Bionic versions don't have sys/user.h, so we just define regs_struct
+// directly. This can be removed once we no longer need to support these old
+// Bionic versions.
+struct regs_struct {
+ unsigned long uregs[18];
+};
+#else
+typedef user_regs regs_struct;
+#endif
+
+#define REG_cpsr uregs[16]
+#define REG_pc uregs[15]
+#define REG_lr uregs[14]
+#define REG_sp uregs[13]
+#define REG_ip uregs[12]
+#define REG_fp uregs[11]
+#define REG_r10 uregs[10]
+#define REG_r9 uregs[9]
+#define REG_r8 uregs[8]
+#define REG_r7 uregs[7]
+#define REG_r6 uregs[6]
+#define REG_r5 uregs[5]
+#define REG_r4 uregs[4]
+#define REG_r3 uregs[3]
+#define REG_r2 uregs[2]
+#define REG_r1 uregs[1]
+#define REG_r0 uregs[0]
+#define REG_ORIG_r0 uregs[17]
+
+#define SECCOMP_PT_RESULT(_regs) (_regs).REG_r0
+#define SECCOMP_PT_SYSCALL(_regs) (_regs).REG_r7
+#define SECCOMP_PT_IP(_regs) (_regs).REG_pc
+#define SECCOMP_PT_PARM1(_regs) (_regs).REG_r0
+#define SECCOMP_PT_PARM2(_regs) (_regs).REG_r1
+#define SECCOMP_PT_PARM3(_regs) (_regs).REG_r2
+#define SECCOMP_PT_PARM4(_regs) (_regs).REG_r3
+#define SECCOMP_PT_PARM5(_regs) (_regs).REG_r4
+#define SECCOMP_PT_PARM6(_regs) (_regs).REG_r5
+
#else
#error Unsupported target platform
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index c5c6f61..6ecbca9 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -613,7 +613,7 @@
// and of course, we make sure to only ever enable this feature if it
// is actually requested by the sandbox policy.
if (has_unsafe_traps) {
- if (SandboxSyscall(-1) == -1 && errno == ENOSYS) {
+ if (Syscall::Call(-1) == -1 && errno == ENOSYS) {
SANDBOX_DIE(
"Support for UnsafeTrap() has not yet been ported to this "
"architecture");
@@ -650,9 +650,8 @@
gen->Traverse(jumptable, RedirectToUserspace, this);
// Allow system calls, if they originate from our magic return address
- // (which we can query by calling SandboxSyscall(-1)).
- uintptr_t syscall_entry_point =
- static_cast<uintptr_t>(SandboxSyscall(-1));
+ // (which we can query by calling Syscall::Call(-1)).
+ uintptr_t syscall_entry_point = static_cast<uintptr_t>(Syscall::Call(-1));
uint32_t low = static_cast<uint32_t>(syscall_entry_point);
#if __SIZEOF_POINTER__ > 4
uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32);
@@ -1003,13 +1002,13 @@
}
intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) {
- return SandboxSyscall(args.nr,
- static_cast<intptr_t>(args.args[0]),
- static_cast<intptr_t>(args.args[1]),
- static_cast<intptr_t>(args.args[2]),
- static_cast<intptr_t>(args.args[3]),
- static_cast<intptr_t>(args.args[4]),
- static_cast<intptr_t>(args.args[5]));
+ return Syscall::Call(args.nr,
+ static_cast<intptr_t>(args.args[0]),
+ static_cast<intptr_t>(args.args[1]),
+ static_cast<intptr_t>(args.args[2]),
+ static_cast<intptr_t>(args.args[3]),
+ static_cast<intptr_t>(args.args[4]),
+ static_cast<intptr_t>(args.args[5]));
}
ErrorCode SandboxBPF::Cond(int argno,
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index 9bb414a..32fe2a7 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -25,6 +25,7 @@
namespace sandbox {
+// This must match the kernel's seccomp_data structure.
struct arch_seccomp_data {
int nr;
uint32_t arch;
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index 0341d2f..06ba209 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -5,7 +5,9 @@
#include <errno.h>
#include <pthread.h>
#include <sched.h>
+#include <signal.h>
#include <sys/prctl.h>
+#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -24,6 +26,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
@@ -1201,7 +1204,7 @@
// based on the system call number and the parameters that we decided
// to pass in. Verify that this condition holds true.
BPF_ASSERT(
- SandboxSyscall(
+ Syscall::Call(
sysno, args[0], args[1], args[2], args[3], args[4], args[5]) ==
-err);
}
@@ -1276,18 +1279,18 @@
}
BPF_TEST_C(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) {
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0x55555555) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0xAAAAAAAA) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0, 0x55555555) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0, 0xAAAAAAAA) == -2);
#if __SIZEOF_POINTER__ > 4
// On 32bit machines, there is no way to pass a 64bit argument through the
// syscall interface. So, we have to skip the part of the test that requires
// 64bit arguments.
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555AAAAAAAAULL) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555500000000ULL) == -2);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555511111111ULL) == -2);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x55555555AAAAAAAAULL) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x5555555500000000ULL) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x5555555511111111ULL) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2);
#else
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x55555555) == -2);
#endif
}
@@ -1299,7 +1302,7 @@
EqualityArgumentUnallowed64bit,
DEATH_MESSAGE("Unexpected 64bit argument detected"),
EqualityArgumentWidthPolicy) {
- SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL);
+ Syscall::Call(__NR_uname, 0, 0x5555555555555555ULL);
}
#endif
@@ -1327,9 +1330,9 @@
BPF_TEST_C(SandboxBPF,
EqualityWithNegativeArguments,
EqualityWithNegativeArgumentsPolicy) {
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, -1) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, -1LL) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, -1) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, -1LL) == -1);
}
#if __SIZEOF_POINTER__ > 4
@@ -1340,7 +1343,7 @@
// When expecting a 32bit system call argument, we look at the MSB of the
// 64bit value and allow both "0" and "-1". But the latter is allowed only
// iff the LSB was negative. So, this death test should error out.
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF00000000LL) == -1);
}
#endif
class AllBitTestPolicy : public SandboxBPFPolicy {
@@ -1430,10 +1433,10 @@
// to make changes to these values, you will have to edit the
// test policy instead.
#define BITMASK_TEST(testcase, arg, op, mask, expected_value) \
- BPF_ASSERT(SandboxSyscall(__NR_uname, (testcase), (arg)) == (expected_value))
+ BPF_ASSERT(Syscall::Call(__NR_uname, (testcase), (arg)) == (expected_value))
// Our uname() system call returns ErrorCode(1) for success and
-// ErrorCode(0) for failure. SandboxSyscall() turns this into an
+// ErrorCode(0) for failure. Syscall::Call() turns this into an
// exit code of -1 or 0.
#define EXPECT_FAILURE 0
#define EXPECT_SUCCESS -1
@@ -1863,7 +1866,7 @@
static void* ThreadFnc(void* arg) {
++*reinterpret_cast<int*>(arg);
- SandboxSyscall(__NR_futex, arg, FUTEX_WAKE, 1, 0, 0, 0);
+ Syscall::Call(__NR_futex, arg, FUTEX_WAKE, 1, 0, 0, 0);
return NULL;
}
@@ -1882,7 +1885,7 @@
BPF_ASSERT(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
BPF_ASSERT(!pthread_create(&thread, &attr, ThreadFnc, &thread_ran));
BPF_ASSERT(!pthread_attr_destroy(&attr));
- while (SandboxSyscall(__NR_futex, &thread_ran, FUTEX_WAIT, 0, 0, 0, 0) ==
+ while (Syscall::Call(__NR_futex, &thread_ran, FUTEX_WAIT, 0, 0, 0, 0) ==
-EINTR) {
}
BPF_ASSERT(thread_ran);
@@ -1893,11 +1896,11 @@
// run-time libraries other than glibc might call __NR_fork instead of
// __NR_clone, and that would introduce a bogus test failure.
int pid;
- BPF_ASSERT(SandboxSyscall(__NR_clone,
- CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,
- 0,
- 0,
- &pid) == -EPERM);
+ BPF_ASSERT(Syscall::Call(__NR_clone,
+ CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,
+ 0,
+ 0,
+ &pid) == -EPERM);
}
BPF_TEST_C(SandboxBPF, PthreadEquality, PthreadPolicyEquality) {
@@ -1908,6 +1911,154 @@
PthreadTest();
}
+// libc might not define these even though the kernel supports it.
+#ifndef PTRACE_O_TRACESECCOMP
+#define PTRACE_O_TRACESECCOMP 0x00000080
+#endif
+
+#ifdef PTRACE_EVENT_SECCOMP
+#define IS_SECCOMP_EVENT(status) ((status >> 16) == PTRACE_EVENT_SECCOMP)
+#else
+// When Debian/Ubuntu backported seccomp-bpf support into earlier kernels, they
+// changed the value of PTRACE_EVENT_SECCOMP from 7 to 8, since 7 was taken by
+// PTRACE_EVENT_STOP (upstream chose to renumber PTRACE_EVENT_STOP to 128). If
+// PTRACE_EVENT_SECCOMP isn't defined, we have no choice but to consider both
+// values here.
+#define IS_SECCOMP_EVENT(status) ((status >> 16) == 7 || (status >> 16) == 8)
+#endif
+
+#if defined(__arm__)
+#ifndef PTRACE_SET_SYSCALL
+#define PTRACE_SET_SYSCALL 23
+#endif
+#endif
+
+// Changes the syscall to run for a child being sandboxed using seccomp-bpf with
+// PTRACE_O_TRACESECCOMP. Should only be called when the child is stopped on
+// PTRACE_EVENT_SECCOMP.
+//
+// regs should contain the current set of registers of the child, obtained using
+// PTRACE_GETREGS.
+//
+// Depending on the architecture, this may modify regs, so the caller is
+// responsible for committing these changes using PTRACE_SETREGS.
+long SetSyscall(pid_t pid, regs_struct* regs, int syscall_number) {
+#if defined(__arm__)
+ // On ARM, the syscall is changed using PTRACE_SET_SYSCALL. We cannot use the
+ // libc ptrace call as the request parameter is an enum, and
+ // PTRACE_SET_SYSCALL may not be in the enum.
+ return syscall(__NR_ptrace, PTRACE_SET_SYSCALL, pid, NULL, syscall_number);
+#endif
+
+ SECCOMP_PT_SYSCALL(*regs) = syscall_number;
+ return 0;
+}
+
+const uint16_t kTraceData = 0xcc;
+
+class TraceAllPolicy : public SandboxBPFPolicy {
+ public:
+ TraceAllPolicy() {}
+ virtual ~TraceAllPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE {
+ return ErrorCode(ErrorCode::ERR_TRACE + kTraceData);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TraceAllPolicy);
+};
+
+SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) {
+ if (SandboxBPF::SupportsSeccompSandbox(-1) !=
+ sandbox::SandboxBPF::STATUS_AVAILABLE) {
+ return;
+ }
+
+#if defined(__arm__)
+ printf("This test is currently disabled on ARM due to a kernel bug.");
+ return;
+#endif
+
+ pid_t pid = fork();
+ BPF_ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ pid_t my_pid = getpid();
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_TRACEME, -1, NULL, NULL));
+ BPF_ASSERT_EQ(0, raise(SIGSTOP));
+ SandboxBPF sandbox;
+ sandbox.SetSandboxPolicy(new TraceAllPolicy);
+ BPF_ASSERT(sandbox.StartSandbox(SandboxBPF::PROCESS_SINGLE_THREADED));
+
+ // getpid is allowed.
+ BPF_ASSERT_EQ(my_pid, syscall(__NR_getpid));
+
+ // write to stdout is skipped and returns a fake value.
+ BPF_ASSERT_EQ(kExpectedReturnValue,
+ syscall(__NR_write, STDOUT_FILENO, "A", 1));
+
+ // kill is rewritten to exit(kExpectedReturnValue).
+ syscall(__NR_kill, my_pid, SIGKILL);
+
+ // Should not be reached.
+ BPF_ASSERT(false);
+ }
+
+ int status;
+ BPF_ASSERT(HANDLE_EINTR(waitpid(pid, &status, WUNTRACED)) != -1);
+ BPF_ASSERT(WIFSTOPPED(status));
+
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_SETOPTIONS, pid, NULL,
+ reinterpret_cast<void*>(PTRACE_O_TRACESECCOMP)));
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_CONT, pid, NULL, NULL));
+ while (true) {
+ BPF_ASSERT(HANDLE_EINTR(waitpid(pid, &status, 0)) != -1);
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ BPF_ASSERT(WIFEXITED(status));
+ BPF_ASSERT_EQ(kExpectedReturnValue, WEXITSTATUS(status));
+ break;
+ }
+
+ if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP ||
+ !IS_SECCOMP_EVENT(status)) {
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_CONT, pid, NULL, NULL));
+ continue;
+ }
+
+ unsigned long data;
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data));
+ BPF_ASSERT_EQ(kTraceData, data);
+
+ regs_struct regs;
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_GETREGS, pid, NULL, ®s));
+ switch (SECCOMP_PT_SYSCALL(regs)) {
+ case __NR_write:
+ // Skip writes to stdout, make it return kExpectedReturnValue. Allow
+ // writes to stderr so that BPF_ASSERT messages show up.
+ if (SECCOMP_PT_PARM1(regs) == STDOUT_FILENO) {
+ BPF_ASSERT_NE(-1, SetSyscall(pid, ®s, -1));
+ SECCOMP_PT_RESULT(regs) = kExpectedReturnValue;
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_SETREGS, pid, NULL, ®s));
+ }
+ break;
+
+ case __NR_kill:
+ // Rewrite to exit(kExpectedReturnValue).
+ BPF_ASSERT_NE(-1, SetSyscall(pid, ®s, __NR_exit));
+ SECCOMP_PT_PARM1(regs) = kExpectedReturnValue;
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_SETREGS, pid, NULL, ®s));
+ break;
+
+ default:
+ // Allow all other syscalls.
+ break;
+ }
+
+ BPF_ASSERT_NE(-1, ptrace(PTRACE_CONT, pid, NULL, NULL));
+ }
+}
+
} // namespace
} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index fd599e8..64c0b8e 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -11,169 +11,177 @@
namespace sandbox {
- asm( // We need to be able to tell the kernel exactly where we made a
- // system call. The C++ compiler likes to sometimes clone or
- // inline code, which would inadvertently end up duplicating
- // the entry point.
- // "gcc" can suppress code duplication with suitable function
- // attributes, but "clang" doesn't have this ability.
- // The "clang" developer mailing list suggested that the correct
- // and portable solution is a file-scope assembly block.
- // N.B. We do mark our code as a proper function so that backtraces
- // work correctly. But we make absolutely no attempt to use the
- // ABI's calling conventions for passing arguments. We will only
- // ever be called from assembly code and thus can pick more
- // suitable calling conventions.
-#if defined(__i386__)
- ".text\n"
- ".align 16, 0x90\n"
- ".type SyscallAsm, @function\n"
- "SyscallAsm:.cfi_startproc\n"
- // Check if "%eax" is negative. If so, do not attempt to make a
- // system call. Instead, compute the return address that is visible
- // to the kernel after we execute "int $0x80". This address can be
- // used as a marker that BPF code inspects.
- "test %eax, %eax\n"
- "jge 1f\n"
- // Always, make sure that our code is position-independent, or
- // address space randomization might not work on i386. This means,
- // we can't use "lea", but instead have to rely on "call/pop".
- "call 0f; .cfi_adjust_cfa_offset 4\n"
- "0:pop %eax; .cfi_adjust_cfa_offset -4\n"
- "addl $2f-0b, %eax\n"
- "ret\n"
- // Save register that we don't want to clobber. On i386, we need to
- // save relatively aggressively, as there are a couple or registers
- // that are used internally (e.g. %ebx for position-independent
- // code, and %ebp for the frame pointer), and as we need to keep at
- // least a few registers available for the register allocator.
- "1:push %esi; .cfi_adjust_cfa_offset 4\n"
- "push %edi; .cfi_adjust_cfa_offset 4\n"
- "push %ebx; .cfi_adjust_cfa_offset 4\n"
- "push %ebp; .cfi_adjust_cfa_offset 4\n"
- // Copy entries from the array holding the arguments into the
- // correct CPU registers.
- "movl 0(%edi), %ebx\n"
- "movl 4(%edi), %ecx\n"
- "movl 8(%edi), %edx\n"
- "movl 12(%edi), %esi\n"
- "movl 20(%edi), %ebp\n"
- "movl 16(%edi), %edi\n"
- // Enter the kernel.
- "int $0x80\n"
- // This is our "magic" return address that the BPF filter sees.
- "2:"
- // Restore any clobbered registers that we didn't declare to the
- // compiler.
- "pop %ebp; .cfi_adjust_cfa_offset -4\n"
- "pop %ebx; .cfi_adjust_cfa_offset -4\n"
- "pop %edi; .cfi_adjust_cfa_offset -4\n"
- "pop %esi; .cfi_adjust_cfa_offset -4\n"
- "ret\n"
- ".cfi_endproc\n"
- "9:.size SyscallAsm, 9b-SyscallAsm\n"
-#elif defined(__x86_64__)
- ".text\n"
- ".align 16, 0x90\n"
- ".type SyscallAsm, @function\n"
- "SyscallAsm:.cfi_startproc\n"
- // Check if "%rax" is negative. If so, do not attempt to make a
- // system call. Instead, compute the return address that is visible
- // to the kernel after we execute "syscall". This address can be
- // used as a marker that BPF code inspects.
- "test %rax, %rax\n"
- "jge 1f\n"
- // Always make sure that our code is position-independent, or the
- // linker will throw a hissy fit on x86-64.
- "call 0f; .cfi_adjust_cfa_offset 8\n"
- "0:pop %rax; .cfi_adjust_cfa_offset -8\n"
- "addq $2f-0b, %rax\n"
- "ret\n"
- // We declared all clobbered registers to the compiler. On x86-64,
- // there really isn't much of a problem with register pressure. So,
- // we can go ahead and directly copy the entries from the arguments
- // array into the appropriate CPU registers.
- "1:movq 0(%r12), %rdi\n"
- "movq 8(%r12), %rsi\n"
- "movq 16(%r12), %rdx\n"
- "movq 24(%r12), %r10\n"
- "movq 32(%r12), %r8\n"
- "movq 40(%r12), %r9\n"
- // Enter the kernel.
- "syscall\n"
- // This is our "magic" return address that the BPF filter sees.
- "2:ret\n"
- ".cfi_endproc\n"
- "9:.size SyscallAsm, 9b-SyscallAsm\n"
-#elif defined(__arm__)
- // Throughout this file, we use the same mode (ARM vs. thumb)
- // that the C++ compiler uses. This means, when transfering control
- // from C++ to assembly code, we do not need to switch modes (e.g.
- // by using the "bx" instruction). It also means that our assembly
- // code should not be invoked directly from code that lives in
- // other compilation units, as we don't bother implementing thumb
- // interworking. That's OK, as we don't make any of the assembly
- // symbols public. They are all local to this file.
- ".text\n"
- ".align 2\n"
- ".type SyscallAsm, %function\n"
-#if defined(__thumb__)
- ".thumb_func\n"
-#else
- ".arm\n"
-#endif
- "SyscallAsm:.fnstart\n"
- "@ args = 0, pretend = 0, frame = 8\n"
- "@ frame_needed = 1, uses_anonymous_args = 0\n"
-#if defined(__thumb__)
- ".cfi_startproc\n"
- "push {r7, lr}\n"
- ".cfi_offset 14, -4\n"
- ".cfi_offset 7, -8\n"
- "mov r7, sp\n"
- ".cfi_def_cfa_register 7\n"
- ".cfi_def_cfa_offset 8\n"
-#else
- "stmfd sp!, {fp, lr}\n"
- "add fp, sp, #4\n"
-#endif
- // Check if "r0" is negative. If so, do not attempt to make a
- // system call. Instead, compute the return address that is visible
- // to the kernel after we execute "swi 0". This address can be
- // used as a marker that BPF code inspects.
- "cmp r0, #0\n"
- "bge 1f\n"
- "adr r0, 2f\n"
- "b 2f\n"
- // We declared (almost) all clobbered registers to the compiler. On
- // ARM there is no particular register pressure. So, we can go
- // ahead and directly copy the entries from the arguments array
- // into the appropriate CPU registers.
- "1:ldr r5, [r6, #20]\n"
- "ldr r4, [r6, #16]\n"
- "ldr r3, [r6, #12]\n"
- "ldr r2, [r6, #8]\n"
- "ldr r1, [r6, #4]\n"
- "mov r7, r0\n"
- "ldr r0, [r6, #0]\n"
- // Enter the kernel
- "swi 0\n"
- // Restore the frame pointer. Also restore the program counter from
- // the link register; this makes us return to the caller.
-#if defined(__thumb__)
- "2:pop {r7, pc}\n"
- ".cfi_endproc\n"
-#else
- "2:ldmfd sp!, {fp, pc}\n"
-#endif
- ".fnend\n"
- "9:.size SyscallAsm, 9b-SyscallAsm\n"
-#endif
- ); // asm
+namespace {
-intptr_t SandboxSyscall(int nr,
- intptr_t p0, intptr_t p1, intptr_t p2,
- intptr_t p3, intptr_t p4, intptr_t p5) {
+asm(// We need to be able to tell the kernel exactly where we made a
+ // system call. The C++ compiler likes to sometimes clone or
+ // inline code, which would inadvertently end up duplicating
+ // the entry point.
+ // "gcc" can suppress code duplication with suitable function
+ // attributes, but "clang" doesn't have this ability.
+ // The "clang" developer mailing list suggested that the correct
+ // and portable solution is a file-scope assembly block.
+ // N.B. We do mark our code as a proper function so that backtraces
+ // work correctly. But we make absolutely no attempt to use the
+ // ABI's calling conventions for passing arguments. We will only
+ // ever be called from assembly code and thus can pick more
+ // suitable calling conventions.
+#if defined(__i386__)
+ ".text\n"
+ ".align 16, 0x90\n"
+ ".type SyscallAsm, @function\n"
+ "SyscallAsm:.cfi_startproc\n"
+ // Check if "%eax" is negative. If so, do not attempt to make a
+ // system call. Instead, compute the return address that is visible
+ // to the kernel after we execute "int $0x80". This address can be
+ // used as a marker that BPF code inspects.
+ "test %eax, %eax\n"
+ "jge 1f\n"
+ // Always, make sure that our code is position-independent, or
+ // address space randomization might not work on i386. This means,
+ // we can't use "lea", but instead have to rely on "call/pop".
+ "call 0f; .cfi_adjust_cfa_offset 4\n"
+ "0:pop %eax; .cfi_adjust_cfa_offset -4\n"
+ "addl $2f-0b, %eax\n"
+ "ret\n"
+ // Save register that we don't want to clobber. On i386, we need to
+ // save relatively aggressively, as there are a couple or registers
+ // that are used internally (e.g. %ebx for position-independent
+ // code, and %ebp for the frame pointer), and as we need to keep at
+ // least a few registers available for the register allocator.
+ "1:push %esi; .cfi_adjust_cfa_offset 4\n"
+ "push %edi; .cfi_adjust_cfa_offset 4\n"
+ "push %ebx; .cfi_adjust_cfa_offset 4\n"
+ "push %ebp; .cfi_adjust_cfa_offset 4\n"
+ // Copy entries from the array holding the arguments into the
+ // correct CPU registers.
+ "movl 0(%edi), %ebx\n"
+ "movl 4(%edi), %ecx\n"
+ "movl 8(%edi), %edx\n"
+ "movl 12(%edi), %esi\n"
+ "movl 20(%edi), %ebp\n"
+ "movl 16(%edi), %edi\n"
+ // Enter the kernel.
+ "int $0x80\n"
+ // This is our "magic" return address that the BPF filter sees.
+ "2:"
+ // Restore any clobbered registers that we didn't declare to the
+ // compiler.
+ "pop %ebp; .cfi_adjust_cfa_offset -4\n"
+ "pop %ebx; .cfi_adjust_cfa_offset -4\n"
+ "pop %edi; .cfi_adjust_cfa_offset -4\n"
+ "pop %esi; .cfi_adjust_cfa_offset -4\n"
+ "ret\n"
+ ".cfi_endproc\n"
+ "9:.size SyscallAsm, 9b-SyscallAsm\n"
+#elif defined(__x86_64__)
+ ".text\n"
+ ".align 16, 0x90\n"
+ ".type SyscallAsm, @function\n"
+ "SyscallAsm:.cfi_startproc\n"
+ // Check if "%rax" is negative. If so, do not attempt to make a
+ // system call. Instead, compute the return address that is visible
+ // to the kernel after we execute "syscall". This address can be
+ // used as a marker that BPF code inspects.
+ "test %rax, %rax\n"
+ "jge 1f\n"
+ // Always make sure that our code is position-independent, or the
+ // linker will throw a hissy fit on x86-64.
+ "call 0f; .cfi_adjust_cfa_offset 8\n"
+ "0:pop %rax; .cfi_adjust_cfa_offset -8\n"
+ "addq $2f-0b, %rax\n"
+ "ret\n"
+ // We declared all clobbered registers to the compiler. On x86-64,
+ // there really isn't much of a problem with register pressure. So,
+ // we can go ahead and directly copy the entries from the arguments
+ // array into the appropriate CPU registers.
+ "1:movq 0(%r12), %rdi\n"
+ "movq 8(%r12), %rsi\n"
+ "movq 16(%r12), %rdx\n"
+ "movq 24(%r12), %r10\n"
+ "movq 32(%r12), %r8\n"
+ "movq 40(%r12), %r9\n"
+ // Enter the kernel.
+ "syscall\n"
+ // This is our "magic" return address that the BPF filter sees.
+ "2:ret\n"
+ ".cfi_endproc\n"
+ "9:.size SyscallAsm, 9b-SyscallAsm\n"
+#elif defined(__arm__)
+ // Throughout this file, we use the same mode (ARM vs. thumb)
+ // that the C++ compiler uses. This means, when transfering control
+ // from C++ to assembly code, we do not need to switch modes (e.g.
+ // by using the "bx" instruction). It also means that our assembly
+ // code should not be invoked directly from code that lives in
+ // other compilation units, as we don't bother implementing thumb
+ // interworking. That's OK, as we don't make any of the assembly
+ // symbols public. They are all local to this file.
+ ".text\n"
+ ".align 2\n"
+ ".type SyscallAsm, %function\n"
+#if defined(__thumb__)
+ ".thumb_func\n"
+#else
+ ".arm\n"
+#endif
+ "SyscallAsm:.fnstart\n"
+ "@ args = 0, pretend = 0, frame = 8\n"
+ "@ frame_needed = 1, uses_anonymous_args = 0\n"
+#if defined(__thumb__)
+ ".cfi_startproc\n"
+ "push {r7, lr}\n"
+ ".cfi_offset 14, -4\n"
+ ".cfi_offset 7, -8\n"
+ "mov r7, sp\n"
+ ".cfi_def_cfa_register 7\n"
+ ".cfi_def_cfa_offset 8\n"
+#else
+ "stmfd sp!, {fp, lr}\n"
+ "add fp, sp, #4\n"
+#endif
+ // Check if "r0" is negative. If so, do not attempt to make a
+ // system call. Instead, compute the return address that is visible
+ // to the kernel after we execute "swi 0". This address can be
+ // used as a marker that BPF code inspects.
+ "cmp r0, #0\n"
+ "bge 1f\n"
+ "adr r0, 2f\n"
+ "b 2f\n"
+ // We declared (almost) all clobbered registers to the compiler. On
+ // ARM there is no particular register pressure. So, we can go
+ // ahead and directly copy the entries from the arguments array
+ // into the appropriate CPU registers.
+ "1:ldr r5, [r6, #20]\n"
+ "ldr r4, [r6, #16]\n"
+ "ldr r3, [r6, #12]\n"
+ "ldr r2, [r6, #8]\n"
+ "ldr r1, [r6, #4]\n"
+ "mov r7, r0\n"
+ "ldr r0, [r6, #0]\n"
+ // Enter the kernel
+ "swi 0\n"
+// Restore the frame pointer. Also restore the program counter from
+// the link register; this makes us return to the caller.
+#if defined(__thumb__)
+ "2:pop {r7, pc}\n"
+ ".cfi_endproc\n"
+#else
+ "2:ldmfd sp!, {fp, pc}\n"
+#endif
+ ".fnend\n"
+ "9:.size SyscallAsm, 9b-SyscallAsm\n"
+#endif
+ ); // asm
+
+} // namespace
+
+intptr_t Syscall::Call(int nr,
+ intptr_t p0,
+ intptr_t p1,
+ intptr_t p2,
+ intptr_t p3,
+ intptr_t p4,
+ intptr_t p5) {
// We rely on "intptr_t" to be the exact size as a "void *". This is
// typically true, but just in case, we add a check. The language
// specification allows platforms some leeway in cases, where
@@ -181,61 +189,78 @@
// that this would only be an issue for IA64, which we are currently not
// planning on supporting. And it is even possible that this would work
// on IA64, but for lack of actual hardware, I cannot test.
- COMPILE_ASSERT(sizeof(void *) == sizeof(intptr_t),
+ COMPILE_ASSERT(sizeof(void*) == sizeof(intptr_t),
pointer_types_and_intptr_must_be_exactly_the_same_size);
- const intptr_t args[6] = { p0, p1, p2, p3, p4, p5 };
+ const intptr_t args[6] = {p0, p1, p2, p3, p4, p5};
- // Invoke our file-scope assembly code. The constraints have been picked
- // carefully to match what the rest of the assembly code expects in input,
- // output, and clobbered registers.
+// Invoke our file-scope assembly code. The constraints have been picked
+// carefully to match what the rest of the assembly code expects in input,
+// output, and clobbered registers.
#if defined(__i386__)
intptr_t ret = nr;
asm volatile(
- "call SyscallAsm\n"
- // N.B. These are not the calling conventions normally used by the ABI.
- : "=a"(ret)
- : "0"(ret), "D"(args)
- : "cc", "esp", "memory", "ecx", "edx");
+ "call SyscallAsm\n"
+ // N.B. These are not the calling conventions normally used by the ABI.
+ : "=a"(ret)
+ : "0"(ret), "D"(args)
+ : "cc", "esp", "memory", "ecx", "edx");
#elif defined(__x86_64__)
intptr_t ret = nr;
{
- register const intptr_t *data __asm__("r12") = args;
+ register const intptr_t* data __asm__("r12") = args;
asm volatile(
- "lea -128(%%rsp), %%rsp\n" // Avoid red zone.
- "call SyscallAsm\n"
- "lea 128(%%rsp), %%rsp\n"
- // N.B. These are not the calling conventions normally used by the ABI.
- : "=a"(ret)
- : "0"(ret), "r"(data)
- : "cc", "rsp", "memory",
- "rcx", "rdi", "rsi", "rdx", "r8", "r9", "r10", "r11");
+ "lea -128(%%rsp), %%rsp\n" // Avoid red zone.
+ "call SyscallAsm\n"
+ "lea 128(%%rsp), %%rsp\n"
+ // N.B. These are not the calling conventions normally used by the ABI.
+ : "=a"(ret)
+ : "0"(ret), "r"(data)
+ : "cc",
+ "rsp",
+ "memory",
+ "rcx",
+ "rdi",
+ "rsi",
+ "rdx",
+ "r8",
+ "r9",
+ "r10",
+ "r11");
}
#elif defined(__arm__)
intptr_t ret;
{
register intptr_t inout __asm__("r0") = nr;
- register const intptr_t *data __asm__("r6") = args;
+ register const intptr_t* data __asm__("r6") = args;
asm volatile(
- "bl SyscallAsm\n"
- // N.B. These are not the calling conventions normally used by the ABI.
- : "=r"(inout)
- : "0"(inout), "r"(data)
- : "cc", "lr", "memory", "r1", "r2", "r3", "r4", "r5"
+ "bl SyscallAsm\n"
+ // N.B. These are not the calling conventions normally used by the ABI.
+ : "=r"(inout)
+ : "0"(inout), "r"(data)
+ : "cc",
+ "lr",
+ "memory",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5"
#if !defined(__thumb__)
- // In thumb mode, we cannot use "r7" as a general purpose register, as
- // it is our frame pointer. We have to manually manage and preserve it.
- // In ARM mode, we have a dedicated frame pointer register and "r7" is
- // thus available as a general purpose register. We don't preserve it,
- // but instead mark it as clobbered.
- , "r7"
+ // In thumb mode, we cannot use "r7" as a general purpose register, as
+ // it is our frame pointer. We have to manually manage and preserve
+ // it.
+ // In ARM mode, we have a dedicated frame pointer register and "r7" is
+ // thus available as a general purpose register. We don't preserve it,
+ // but instead mark it as clobbered.
+ ,
+ "r7"
#endif // !defined(__thumb__)
- );
+ );
ret = inout;
}
#else
- errno = ENOSYS;
- intptr_t ret = -1;
+#error "Unimplemented architecture"
#endif
return ret;
}
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h
index f444d3a..57970a3 100644
--- a/sandbox/linux/seccomp-bpf/syscall.h
+++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -7,141 +7,82 @@
#include <stdint.h>
+#include "base/macros.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
-// We have to make sure that we have a single "magic" return address for
-// our system calls, which we can check from within a BPF filter. This
-// works by writing a little bit of asm() code that a) enters the kernel, and
-// that also b) can be invoked in a way that computes this return address.
-// Passing "nr" as "-1" computes the "magic" return address. Passing any
-// other value invokes the appropriate system call.
-SANDBOX_EXPORT intptr_t SandboxSyscall(int nr,
- intptr_t p0,
- intptr_t p1,
- intptr_t p2,
- intptr_t p3,
- intptr_t p4,
- intptr_t p5);
+// This purely static class can be used to perform system calls with some
+// low-level control.
+class SANDBOX_EXPORT Syscall {
+ public:
+ // This performs system call |nr| with the arguments p0 to p5 from a constant
+ // userland address, which is for instance observable by seccomp-bpf filters.
+ // The constant userland address from which these system calls are made will
+ // be returned if |nr| is passed as -1.
+ // On error, this function will return a value between -1 and -4095 which
+ // should be interpreted as -errno.
+ static intptr_t Call(int nr,
+ intptr_t p0,
+ intptr_t p1,
+ intptr_t p2,
+ intptr_t p3,
+ intptr_t p4,
+ intptr_t p5);
-// System calls can take up to six parameters. Traditionally, glibc
-// implements this property by using variadic argument lists. This works, but
-// confuses modern tools such as valgrind, because we are nominally passing
-// uninitialized data whenever we call through this function and pass less
-// than the full six arguments.
-// So, instead, we use C++'s template system to achieve a very similar
-// effect. C++ automatically sets the unused parameters to zero for us, and
-// it also does the correct type expansion (e.g. from 32bit to 64bit) where
-// necessary.
-// We have to use C-style cast operators as we want to be able to accept both
-// integer and pointer types.
-// We explicitly mark all functions as inline. This is not necessary in
-// optimized builds, where the compiler automatically figures out that it
-// can inline everything. But it makes stack traces of unoptimized builds
-// easier to read as it hides implementation details.
-#if __cplusplus >= 201103 // C++11
+ // System calls can take up to six parameters. Traditionally, glibc
+ // implements this property by using variadic argument lists. This works, but
+ // confuses modern tools such as valgrind, because we are nominally passing
+ // uninitialized data whenever we call through this function and pass less
+ // than the full six arguments.
+ // So, instead, we use C++'s template system to achieve a very similar
+ // effect. C++ automatically sets the unused parameters to zero for us, and
+ // it also does the correct type expansion (e.g. from 32bit to 64bit) where
+ // necessary.
+ // We have to use C-style cast operators as we want to be able to accept both
+ // integer and pointer types.
+ template <class T0, class T1, class T2, class T3, class T4, class T5>
+ static inline intptr_t
+ Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
+ return Call(nr,
+ (intptr_t)p0,
+ (intptr_t)p1,
+ (intptr_t)p2,
+ (intptr_t)p3,
+ (intptr_t)p4,
+ (intptr_t)p5);
+ }
-template <class T0 = intptr_t,
- class T1 = intptr_t,
- class T2 = intptr_t,
- class T3 = intptr_t,
- class T4 = intptr_t,
- class T5 = intptr_t>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr,
- T0 p0 = 0,
- T1 p1 = 0,
- T2 p2 = 0,
- T3 p3 = 0,
- T4 p4 = 0,
- T5 p5 = 0)
- __attribute__((always_inline));
+ template <class T0, class T1, class T2, class T3, class T4>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) {
+ return Call(nr, p0, p1, p2, p3, p4, 0);
+ }
-template <class T0, class T1, class T2, class T3, class T4, class T5>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
- return SandboxSyscall(nr,
- (intptr_t)p0,
- (intptr_t)p1,
- (intptr_t)p2,
- (intptr_t)p3,
- (intptr_t)p4,
- (intptr_t)p5);
-}
+ template <class T0, class T1, class T2, class T3>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3) {
+ return Call(nr, p0, p1, p2, p3, 0, 0);
+ }
-#else // Pre-C++11
+ template <class T0, class T1, class T2>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2) {
+ return Call(nr, p0, p1, p2, 0, 0, 0);
+ }
-// TODO(markus): C++11 has a much more concise and readable solution for
-// expressing what we are doing here. Delete the fall-back code for older
-// compilers as soon as we have fully switched to C++11
+ template <class T0, class T1>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1) {
+ return Call(nr, p0, p1, 0, 0, 0, 0);
+ }
-template <class T0, class T1, class T2, class T3, class T4, class T5>
-SANDBOX_EXPORT inline intptr_t
- SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
- __attribute__((always_inline));
-template <class T0, class T1, class T2, class T3, class T4, class T5>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
- return SandboxSyscall(nr,
- (intptr_t)p0,
- (intptr_t)p1,
- (intptr_t)p2,
- (intptr_t)p3,
- (intptr_t)p4,
- (intptr_t)p5);
-}
+ template <class T0>
+ static inline intptr_t Call(int nr, T0 p0) {
+ return Call(nr, p0, 0, 0, 0, 0, 0);
+ }
-template <class T0, class T1, class T2, class T3, class T4>
-SANDBOX_EXPORT inline intptr_t
- SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4)
- __attribute__((always_inline));
-template <class T0, class T1, class T2, class T3, class T4>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) {
- return SandboxSyscall(nr, p0, p1, p2, p3, p4, 0);
-}
+ static inline intptr_t Call(int nr) { return Call(nr, 0, 0, 0, 0, 0, 0); }
-template <class T0, class T1, class T2, class T3>
-SANDBOX_EXPORT inline intptr_t
- SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3)
- __attribute__((always_inline));
-template <class T0, class T1, class T2, class T3>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3) {
- return SandboxSyscall(nr, p0, p1, p2, p3, 0, 0);
-}
-
-template <class T0, class T1, class T2>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2)
- __attribute__((always_inline));
-template <class T0, class T1, class T2>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2) {
- return SandboxSyscall(nr, p0, p1, p2, 0, 0, 0);
-}
-
-template <class T0, class T1>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1)
- __attribute__((always_inline));
-template <class T0, class T1>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1) {
- return SandboxSyscall(nr, p0, p1, 0, 0, 0, 0);
-}
-
-template <class T0>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0)
- __attribute__((always_inline));
-template <class T0>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0) {
- return SandboxSyscall(nr, p0, 0, 0, 0, 0, 0);
-}
-
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr)
- __attribute__((always_inline));
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr) {
- return SandboxSyscall(nr, 0, 0, 0, 0, 0, 0);
-}
-
-#endif // Pre-C++11
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Syscall);
+};
} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index bdeee4f..80b5079 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/posix/eintr_wrapper.h"
+#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
@@ -31,24 +32,25 @@
#endif
TEST(Syscall, WellKnownEntryPoint) {
-// Test that SandboxSyscall(-1) is handled specially. Don't do this on ARM,
+// Test that Syscall::Call(-1) is handled specially. Don't do this on ARM,
// where syscall(-1) crashes with SIGILL. Not running the test is fine, as we
// are still testing ARM code in the next set of tests.
#if !defined(__arm__)
- EXPECT_NE(SandboxSyscall(-1), syscall(-1));
+ EXPECT_NE(Syscall::Call(-1), syscall(-1));
#endif
-// If possible, test that SandboxSyscall(-1) returns the address right after
+// If possible, test that Syscall::Call(-1) returns the address right
+// after
// a kernel entry point.
#if defined(__i386__)
- EXPECT_EQ(0x80CDu, ((uint16_t*)SandboxSyscall(-1))[-1]); // INT 0x80
+ EXPECT_EQ(0x80CDu, ((uint16_t*)Syscall::Call(-1))[-1]); // INT 0x80
#elif defined(__x86_64__)
- EXPECT_EQ(0x050Fu, ((uint16_t*)SandboxSyscall(-1))[-1]); // SYSCALL
+ EXPECT_EQ(0x050Fu, ((uint16_t*)Syscall::Call(-1))[-1]); // SYSCALL
#elif defined(__arm__)
#if defined(__thumb__)
- EXPECT_EQ(0xDF00u, ((uint16_t*)SandboxSyscall(-1))[-1]); // SWI 0
+ EXPECT_EQ(0xDF00u, ((uint16_t*)Syscall::Call(-1))[-1]); // SWI 0
#else
- EXPECT_EQ(0xEF000000u, ((uint32_t*)SandboxSyscall(-1))[-1]); // SVC 0
+ EXPECT_EQ(0xEF000000u, ((uint32_t*)Syscall::Call(-1))[-1]); // SVC 0
#endif
#else
#warning Incomplete test case; need port for target platform
@@ -57,17 +59,25 @@
TEST(Syscall, TrivialSyscallNoArgs) {
// Test that we can do basic system calls
- EXPECT_EQ(SandboxSyscall(__NR_getpid), syscall(__NR_getpid));
+ EXPECT_EQ(Syscall::Call(__NR_getpid), syscall(__NR_getpid));
}
TEST(Syscall, TrivialSyscallOneArg) {
int new_fd;
// Duplicate standard error and close it.
- ASSERT_GE(new_fd = SandboxSyscall(__NR_dup, 2), 0);
- int close_return_value = IGNORE_EINTR(SandboxSyscall(__NR_close, new_fd));
+ ASSERT_GE(new_fd = Syscall::Call(__NR_dup, 2), 0);
+ int close_return_value = IGNORE_EINTR(Syscall::Call(__NR_close, new_fd));
ASSERT_EQ(close_return_value, 0);
}
+TEST(Syscall, TrivialFailingSyscall) {
+ errno = -42;
+ int ret = Syscall::Call(__NR_dup, -1);
+ ASSERT_EQ(-EBADF, ret);
+ // Verify that Syscall::Call does not touch errno.
+ ASSERT_EQ(-42, errno);
+}
+
// SIGSYS trap handler that will be called on __NR_uname.
intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) {
// |aux| is our BPF_AUX pointer.
@@ -91,7 +101,8 @@
}
}
-// We are testing SandboxSyscall() by making use of a BPF filter that allows us
+// We are testing Syscall::Call() by making use of a BPF filter that
+// allows us
// to inspect the system call arguments that the kernel saw.
BPF_TEST(Syscall,
SyntheticSixArgs,
@@ -109,13 +120,13 @@
// We could use pretty much any system call we don't need here. uname() is
// nice because it doesn't have any dangerous side effects.
- BPF_ASSERT(SandboxSyscall(__NR_uname,
- syscall_args[0],
- syscall_args[1],
- syscall_args[2],
- syscall_args[3],
- syscall_args[4],
- syscall_args[5]) == -ENOMEM);
+ BPF_ASSERT(Syscall::Call(__NR_uname,
+ syscall_args[0],
+ syscall_args[1],
+ syscall_args[2],
+ syscall_args[3],
+ syscall_args[4],
+ syscall_args[5]) == -ENOMEM);
// We expect the trap handler to have copied the 6 arguments.
BPF_ASSERT(BPF_AUX->size() == 6);
@@ -133,69 +144,69 @@
TEST(Syscall, ComplexSyscallSixArgs) {
int fd;
- ASSERT_LE(0, fd = SandboxSyscall(__NR_open, "/dev/null", O_RDWR, 0L));
+ ASSERT_LE(0, fd = Syscall::Call(__NR_open, "/dev/null", O_RDWR, 0L));
// Use mmap() to allocate some read-only memory
char* addr0;
- ASSERT_NE((char*)NULL,
- addr0 = reinterpret_cast<char*>(
- SandboxSyscall(kMMapNr,
- (void*)NULL,
- 4096,
- PROT_READ,
- MAP_PRIVATE | MAP_ANONYMOUS,
- fd,
- 0L)));
+ ASSERT_NE(
+ (char*)NULL,
+ addr0 = reinterpret_cast<char*>(Syscall::Call(kMMapNr,
+ (void*)NULL,
+ 4096,
+ PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ fd,
+ 0L)));
// Try to replace the existing mapping with a read-write mapping
char* addr1;
ASSERT_EQ(addr0,
addr1 = reinterpret_cast<char*>(
- SandboxSyscall(kMMapNr,
- addr0,
- 4096L,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
- fd,
- 0L)));
+ Syscall::Call(kMMapNr,
+ addr0,
+ 4096L,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ fd,
+ 0L)));
++*addr1; // This should not seg fault
// Clean up
- EXPECT_EQ(0, SandboxSyscall(__NR_munmap, addr1, 4096L));
- EXPECT_EQ(0, IGNORE_EINTR(SandboxSyscall(__NR_close, fd)));
+ EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr1, 4096L));
+ EXPECT_EQ(0, IGNORE_EINTR(Syscall::Call(__NR_close, fd)));
// Check that the offset argument (i.e. the sixth argument) is processed
// correctly.
- ASSERT_GE(fd = SandboxSyscall(__NR_open, "/proc/self/exe", O_RDONLY, 0L), 0);
+ ASSERT_GE(fd = Syscall::Call(__NR_open, "/proc/self/exe", O_RDONLY, 0L), 0);
char* addr2, *addr3;
ASSERT_NE((char*)NULL,
- addr2 = reinterpret_cast<char*>(SandboxSyscall(
+ addr2 = reinterpret_cast<char*>(Syscall::Call(
kMMapNr, (void*)NULL, 8192L, PROT_READ, MAP_PRIVATE, fd, 0L)));
ASSERT_NE((char*)NULL,
- addr3 = reinterpret_cast<char*>(SandboxSyscall(kMMapNr,
- (void*)NULL,
- 4096L,
- PROT_READ,
- MAP_PRIVATE,
- fd,
+ addr3 = reinterpret_cast<char*>(Syscall::Call(kMMapNr,
+ (void*)NULL,
+ 4096L,
+ PROT_READ,
+ MAP_PRIVATE,
+ fd,
#if defined(__NR_mmap2)
- 1L
+ 1L
#else
- 4096L
+ 4096L
#endif
- )));
+ )));
EXPECT_EQ(0, memcmp(addr2 + 4096, addr3, 4096));
// Just to be absolutely on the safe side, also verify that the file
// contents matches what we are getting from a read() operation.
char buf[8192];
- EXPECT_EQ(8192, SandboxSyscall(__NR_read, fd, buf, 8192L));
+ EXPECT_EQ(8192, Syscall::Call(__NR_read, fd, buf, 8192L));
EXPECT_EQ(0, memcmp(addr2, buf, 8192));
// Clean up
- EXPECT_EQ(0, SandboxSyscall(__NR_munmap, addr2, 8192L));
- EXPECT_EQ(0, SandboxSyscall(__NR_munmap, addr3, 4096L));
- EXPECT_EQ(0, IGNORE_EINTR(SandboxSyscall(__NR_close, fd)));
+ EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr2, 8192L));
+ EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr3, 4096L));
+ EXPECT_EQ(0, IGNORE_EINTR(Syscall::Call(__NR_close, fd)));
}
} // namespace
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index f8b64c9..4c42111 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -168,13 +168,13 @@
if (sigsys.nr == __NR_clone) {
RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler.");
}
- rc = SandboxSyscall(sigsys.nr,
- SECCOMP_PARM1(ctx),
- SECCOMP_PARM2(ctx),
- SECCOMP_PARM3(ctx),
- SECCOMP_PARM4(ctx),
- SECCOMP_PARM5(ctx),
- SECCOMP_PARM6(ctx));
+ rc = Syscall::Call(sigsys.nr,
+ SECCOMP_PARM1(ctx),
+ SECCOMP_PARM2(ctx),
+ SECCOMP_PARM3(ctx),
+ SECCOMP_PARM4(ctx),
+ SECCOMP_PARM5(ctx),
+ SECCOMP_PARM6(ctx));
} else {
const ErrorCode& err = trap_array_[info->si_errno - 1];
if (!err.safe_) {
@@ -227,7 +227,7 @@
// we never return an ErrorCode that is marked as "unsafe". This also
// means, the BPF compiler will never emit code that allow unsafe system
// calls to by-pass the filter (because they use the magic return address
- // from SandboxSyscall(-1)).
+ // from Syscall::Call(-1)).
// This SANDBOX_DIE() can optionally be removed. It won't break security,
// but it might make error messages from the BPF compiler a little harder
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc
index 07b13d6..0863556 100644
--- a/sandbox/linux/seccomp-bpf/verifier.cc
+++ b/sandbox/linux/seccomp-bpf/verifier.cc
@@ -423,10 +423,10 @@
switch (r & SECCOMP_RET_ACTION) {
case SECCOMP_RET_TRAP:
case SECCOMP_RET_ERRNO:
+ case SECCOMP_RET_TRACE:
case SECCOMP_RET_ALLOW:
break;
case SECCOMP_RET_KILL: // We don't ever generate this
- case SECCOMP_RET_TRACE: // We don't ever generate this
case SECCOMP_RET_INVALID: // Should never show up in BPF program
default:
*err = "Unexpected return code found in BPF program";
diff --git a/sandbox/linux/tests/main.cc b/sandbox/linux/tests/main.cc
index 9ee384d..81a0b32 100644
--- a/sandbox/linux/tests/main.cc
+++ b/sandbox/linux/tests/main.cc
@@ -23,11 +23,21 @@
} // namespace
} // namespace sandbox
+#if defined(OS_ANDROID)
+void UnitTestAssertHandler(const std::string& str) {
+ _exit(1);
+}
+#endif
+
int main(int argc, char* argv[]) {
#if defined(OS_ANDROID)
// The use of Callbacks requires an AtExitManager.
base::AtExitManager exit_manager;
testing::InitGoogleTest(&argc, argv);
+ // Death tests rely on LOG(FATAL) triggering an exit (the default behavior is
+ // SIGABRT). The normal test launcher does this at initialization, but since
+ // we still do not use this on Android, we must install the handler ourselves.
+ logging::SetLogAssertHandler(UnitTestAssertHandler);
#endif
// Always go through re-execution for death tests.
// This makes gtest only marginally slower for us and has the
diff --git a/sandbox/mac/BUILD.gn b/sandbox/mac/BUILD.gn
new file mode 100644
index 0000000..e615197
--- /dev/null
+++ b/sandbox/mac/BUILD.gn
@@ -0,0 +1,72 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+component("sandbox") {
+ sources = [
+ "bootstrap_sandbox.cc",
+ "bootstrap_sandbox.h",
+ "launchd_interception_server.cc",
+ "launchd_interception_server.h",
+ "mach_message_server.cc",
+ "mach_message_server.h",
+ "os_compatibility.cc",
+ "os_compatibility.h",
+ "policy.cc",
+ "policy.h",
+ "xpc.h",
+ ]
+
+ defines = [ "SANDBOX_IMPLEMENTATION" ]
+ libs = [ "bsm" ]
+
+ deps = [
+ "//base",
+ ":generate_stubs",
+ ]
+}
+
+generate_stubs_script = "//tools/generate_stubs/generate_stubs.py"
+generate_stubs_header = "xpc_stubs_header.fragment"
+generate_stubs_sig_public = "xpc_stubs.sig"
+generate_stubs_sig_private = "xpc_private_stubs.sig"
+generate_stubs_project = "sandbox/mac"
+generate_stubs_output_stem = "xpc_stubs"
+
+action("generate_stubs") {
+ script = generate_stubs_script
+ sources = [ generate_stubs_sig_public, generate_stubs_sig_private ]
+ source_prereqs = [ generate_stubs_header ]
+ outputs = [
+ "$target_gen_dir/$generate_stubs_output_stem.cc",
+ "$target_gen_dir/$generate_stubs_output_stem.h",
+ ]
+ args = [
+ "-i", rebase_path(target_gen_dir, root_build_dir),
+ "-o", rebase_path(target_gen_dir, root_build_dir),
+ "-t", "posix_stubs",
+ "-e", rebase_path(generate_stubs_header, root_build_dir),
+ "-s", generate_stubs_output_stem,
+ "-p", generate_stubs_project,
+ ]
+ args += rebase_path(sources, root_build_dir)
+}
+
+test("sandbox_mac_unittests") {
+ sources = [
+ "bootstrap_sandbox_unittest.mm",
+ "policy_unittest.cc",
+ ]
+
+ libs = [
+ "CoreFoundation.framework",
+ "Foundation.framework",
+ ]
+
+ deps = [
+ ":sandbox",
+ "//base",
+ "//base/test:run_all_unittests",
+ "//testing/gtest",
+ ]
+}
diff --git a/sandbox/mac/bootstrap_sandbox.cc b/sandbox/mac/bootstrap_sandbox.cc
index b90d8d1..6407c68 100644
--- a/sandbox/mac/bootstrap_sandbox.cc
+++ b/sandbox/mac/bootstrap_sandbox.cc
@@ -60,7 +60,7 @@
int sandbox_policy_id,
const BootstrapSandboxPolicy& policy) {
CHECK(IsPolicyValid(policy));
- CHECK_GT(sandbox_policy_id, 0);
+ CHECK_GT(sandbox_policy_id, kNotAPolicy);
base::AutoLock lock(lock_);
DCHECK(policies_.find(sandbox_policy_id) == policies_.end());
policies_.insert(std::make_pair(sandbox_policy_id, policy));
@@ -102,8 +102,8 @@
void BootstrapSandbox::ChildDied(base::ProcessHandle handle) {
base::AutoLock lock(lock_);
const auto& it = sandboxed_processes_.find(handle);
- CHECK(it != sandboxed_processes_.end());
- sandboxed_processes_.erase(it);
+ if (it != sandboxed_processes_.end())
+ sandboxed_processes_.erase(it);
}
const BootstrapSandboxPolicy* BootstrapSandbox::PolicyForProcess(
diff --git a/sandbox/mac/launchd_interception_server.cc b/sandbox/mac/launchd_interception_server.cc
index 57264aa..70fd33e 100644
--- a/sandbox/mac/launchd_interception_server.cc
+++ b/sandbox/mac/launchd_interception_server.cc
@@ -4,7 +4,6 @@
#include "sandbox/mac/launchd_interception_server.h"
-#include <bsm/libbsm.h>
#include <servers/bootstrap.h>
#include "base/logging.h"
@@ -16,60 +15,24 @@
// The buffer size for all launchd messages. This comes from
// sizeof(union __RequestUnion__vproc_mig_job_subsystem) in launchd, and it
// is larger than the __ReplyUnion.
-const mach_msg_size_t kBufferSize = mach_vm_round_page(2096 +
- sizeof(mach_msg_audit_trailer_t));
+const mach_msg_size_t kBufferSize = 2096;
LaunchdInterceptionServer::LaunchdInterceptionServer(
const BootstrapSandbox* sandbox)
: sandbox_(sandbox),
- server_port_(MACH_PORT_NULL),
- server_queue_(NULL),
- server_source_(NULL),
- did_forward_message_(false),
sandbox_port_(MACH_PORT_NULL),
compat_shim_(GetLaunchdCompatibilityShim()) {
}
LaunchdInterceptionServer::~LaunchdInterceptionServer() {
- if (server_source_)
- dispatch_release(server_source_);
- if (server_queue_)
- dispatch_release(server_queue_);
}
bool LaunchdInterceptionServer::Initialize() {
mach_port_t task = mach_task_self();
kern_return_t kr;
- // Allocate a port for use as a new bootstrap port.
- mach_port_t port;
- if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) !=
- KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate new bootstrap port.";
- return false;
- }
- server_port_.reset(port);
-
- // Allocate the message request and reply buffers.
- const int kMachMsgMemoryFlags = VM_MAKE_TAG(VM_MEMORY_MACH_MSG) |
- VM_FLAGS_ANYWHERE;
- vm_address_t buffer = 0;
-
- kr = vm_allocate(task, &buffer, kBufferSize, kMachMsgMemoryFlags);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate request buffer.";
- return false;
- }
- request_buffer_.reset(buffer, kBufferSize);
-
- kr = vm_allocate(task, &buffer, kBufferSize, kMachMsgMemoryFlags);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to allocate reply buffer.";
- return false;
- }
- reply_buffer_.reset(buffer, kBufferSize);
-
// Allocate the dummy sandbox port.
+ mach_port_t port;
if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) !=
KERN_SUCCESS) {
MACH_LOG(ERROR, kr) << "Failed to allocate dummy sandbox port.";
@@ -83,114 +46,49 @@
}
sandbox_send_port_.reset(sandbox_port_);
- // Set up the dispatch queue to service the bootstrap port.
- // TODO(rsesek): Specify DISPATCH_QUEUE_SERIAL, in the 10.7 SDK. NULL means
- // the same thing but is not symbolically clear.
- server_queue_ = dispatch_queue_create(
- "org.chromium.sandbox.LaunchdInterceptionServer", NULL);
- server_source_ = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
- server_port_.get(), 0, server_queue_);
- dispatch_source_set_event_handler(server_source_, ^{ ReceiveMessage(); });
- dispatch_resume(server_source_);
-
- return true;
-}
-
-void LaunchdInterceptionServer::ReceiveMessage() {
- const mach_msg_options_t kRcvOptions = MACH_RCV_MSG |
- MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
- MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
-
- mach_msg_header_t* request =
- reinterpret_cast<mach_msg_header_t*>(request_buffer_.address());
- mach_msg_header_t* reply =
- reinterpret_cast<mach_msg_header_t*>(reply_buffer_.address());
-
- // Zero out the buffers from handling any previous message.
- bzero(request, kBufferSize);
- bzero(reply, kBufferSize);
- did_forward_message_ = false;
-
- // A Mach message server-once. The system library to run a message server
- // cannot be used here, because some requests are conditionally forwarded
- // to another server.
- kern_return_t kr = mach_msg(request, kRcvOptions, 0, kBufferSize,
- server_port_.get(), MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Unable to receive message.";
- return;
- }
-
- // Set up a reply message in case it will be used.
- reply->msgh_bits = MACH_MSGH_BITS_REMOTE(reply->msgh_bits);
- // Since mach_msg will automatically swap the request and reply ports,
- // undo that.
- reply->msgh_remote_port = request->msgh_remote_port;
- reply->msgh_local_port = MACH_PORT_NULL;
- // MIG servers simply add 100 to the request ID to generate the reply ID.
- reply->msgh_id = request->msgh_id + 100;
-
- // Process the message.
- DemuxMessage(request, reply);
-
- // Free any descriptors in the message body. If the message was forwarded,
- // any descriptors would have been moved out of the process on send. If the
- // forwarded message was sent from the process hosting this sandbox server,
- // destroying the message could also destroy rights held outside the scope of
- // this message server.
- if (!did_forward_message_) {
- mach_msg_destroy(request);
- mach_msg_destroy(reply);
- }
+ message_server_.reset(new MachMessageServer(this, kBufferSize));
+ return message_server_->Initialize();
}
void LaunchdInterceptionServer::DemuxMessage(mach_msg_header_t* request,
mach_msg_header_t* reply) {
VLOG(3) << "Incoming message #" << request->msgh_id;
- // Get the PID of the task that sent this request. This requires getting at
- // the trailer of the message, from the header.
- mach_msg_audit_trailer_t* trailer =
- reinterpret_cast<mach_msg_audit_trailer_t*>(
- reinterpret_cast<vm_address_t>(request) +
- round_msg(request->msgh_size));
- // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
- pid_t sender_pid;
- audit_token_to_au32(trailer->msgh_audit,
- NULL, NULL, NULL, NULL, NULL, &sender_pid, NULL, NULL);
-
- if (sandbox_->PolicyForProcess(sender_pid) == NULL) {
+ pid_t sender_pid = message_server_->GetMessageSenderPID(request);
+ const BootstrapSandboxPolicy* policy =
+ sandbox_->PolicyForProcess(sender_pid);
+ if (policy == NULL) {
// No sandbox policy is in place for the sender of this message, which
// means it is from the sandbox host process or an unsandboxed child.
VLOG(3) << "Message from pid " << sender_pid << " forwarded to launchd";
- ForwardMessage(request, reply);
+ ForwardMessage(request);
return;
}
if (request->msgh_id == compat_shim_.msg_id_look_up2) {
// Filter messages sent via bootstrap_look_up to enforce the sandbox policy
// over the bootstrap namespace.
- HandleLookUp(request, reply, sender_pid);
+ HandleLookUp(request, reply, policy);
} else if (request->msgh_id == compat_shim_.msg_id_swap_integer) {
// Ensure that any vproc_swap_integer requests are safe.
- HandleSwapInteger(request, reply, sender_pid);
+ HandleSwapInteger(request, reply);
} else {
// All other messages are not permitted.
VLOG(1) << "Rejecting unhandled message #" << request->msgh_id;
- RejectMessage(request, reply, MIG_REMOTE_ERROR);
+ message_server_->RejectMessage(reply, MIG_REMOTE_ERROR);
}
}
-void LaunchdInterceptionServer::HandleLookUp(mach_msg_header_t* request,
- mach_msg_header_t* reply,
- pid_t sender_pid) {
+void LaunchdInterceptionServer::HandleLookUp(
+ mach_msg_header_t* request,
+ mach_msg_header_t* reply,
+ const BootstrapSandboxPolicy* policy) {
const std::string request_service_name(
compat_shim_.look_up2_get_request_name(request));
VLOG(2) << "Incoming look_up2 request for " << request_service_name;
- // Find the Rule for this service. If one is not found, use
- // a safe default, POLICY_DENY_ERROR.
- const BootstrapSandboxPolicy* policy = sandbox_->PolicyForProcess(sender_pid);
+ // Find the Rule for this service. If a named rule is not found, use the
+ // default specified by the policy.
const BootstrapSandboxPolicy::NamedRules::const_iterator it =
policy->rules.find(request_service_name);
Rule rule(policy->default_rule);
@@ -201,13 +99,13 @@
// This service is explicitly allowed, so this message will not be
// intercepted by the sandbox.
VLOG(1) << "Permitting and forwarding look_up2: " << request_service_name;
- ForwardMessage(request, reply);
+ ForwardMessage(request);
} else if (rule.result == POLICY_DENY_ERROR) {
// The child is not permitted to look up this service. Send a MIG error
// reply to the client. Returning a NULL or unserviced port for a look up
// can cause clients to crash or hang.
VLOG(1) << "Denying look_up2 with MIG error: " << request_service_name;
- RejectMessage(request, reply, BOOTSTRAP_UNKNOWN_SERVICE);
+ message_server_->RejectMessage(reply, BOOTSTRAP_UNKNOWN_SERVICE);
} else if (rule.result == POLICY_DENY_DUMMY_PORT ||
rule.result == POLICY_SUBSTITUTE_PORT) {
// The policy result is to deny access to the real service port, replying
@@ -227,7 +125,7 @@
// message so that it is not destroyed at the end of ReceiveMessage. The
// above-inserted right has been moved out of the process, and destroying
// the message will unref yet another right.
- if (SendReply(reply))
+ if (message_server_->SendReply(reply))
compat_shim_.look_up2_fill_reply(reply, MACH_PORT_NULL);
} else {
NOTREACHED();
@@ -235,53 +133,20 @@
}
void LaunchdInterceptionServer::HandleSwapInteger(mach_msg_header_t* request,
- mach_msg_header_t* reply,
- pid_t sender_pid) {
+ mach_msg_header_t* reply) {
// Only allow getting information out of launchd. Do not allow setting
// values. Two commonly observed values that are retrieved are
// VPROC_GSK_MGR_PID and VPROC_GSK_TRANSACTIONS_ENABLED.
if (compat_shim_.swap_integer_is_get_only(request)) {
VLOG(2) << "Forwarding vproc swap_integer message.";
- ForwardMessage(request, reply);
+ ForwardMessage(request);
} else {
VLOG(2) << "Rejecting non-read-only swap_integer message.";
- RejectMessage(request, reply, BOOTSTRAP_NOT_PRIVILEGED);
+ message_server_->RejectMessage(reply, BOOTSTRAP_NOT_PRIVILEGED);
}
}
-
-bool LaunchdInterceptionServer::SendReply(mach_msg_header_t* reply) {
- kern_return_t kr = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,
- MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
- << "Unable to send intercepted reply message.";
- return kr == KERN_SUCCESS;
-}
-
-void LaunchdInterceptionServer::ForwardMessage(mach_msg_header_t* request,
- mach_msg_header_t* reply) {
- request->msgh_local_port = request->msgh_remote_port;
- request->msgh_remote_port = sandbox_->real_bootstrap_port();
- // Preserve the msgh_bits that do not deal with the local and remote ports.
- request->msgh_bits = (request->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
- MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE);
- kern_return_t kr = mach_msg_send(request);
- if (kr == KERN_SUCCESS) {
- did_forward_message_ = true;
- } else {
- MACH_LOG(ERROR, kr) << "Unable to forward message to the real launchd.";
- }
-}
-
-void LaunchdInterceptionServer::RejectMessage(mach_msg_header_t* request,
- mach_msg_header_t* reply,
- int error_code) {
- mig_reply_error_t* error_reply = reinterpret_cast<mig_reply_error_t*>(reply);
- error_reply->Head.msgh_size = sizeof(mig_reply_error_t);
- error_reply->Head.msgh_bits =
- MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE);
- error_reply->NDR = NDR_record;
- error_reply->RetCode = error_code;
- SendReply(&error_reply->Head);
+void LaunchdInterceptionServer::ForwardMessage(mach_msg_header_t* request) {
+ message_server_->ForwardMessage(request, sandbox_->real_bootstrap_port());
}
} // namespace sandbox
diff --git a/sandbox/mac/launchd_interception_server.h b/sandbox/mac/launchd_interception_server.h
index 1176533..2e80fec 100644
--- a/sandbox/mac/launchd_interception_server.h
+++ b/sandbox/mac/launchd_interception_server.h
@@ -9,81 +9,55 @@
#include <mach/mach.h>
#include "base/mac/scoped_mach_port.h"
-#include "base/mac/scoped_mach_vm.h"
+#include "base/memory/scoped_ptr.h"
+#include "sandbox/mac/mach_message_server.h"
#include "sandbox/mac/os_compatibility.h"
namespace sandbox {
class BootstrapSandbox;
+struct BootstrapSandboxPolicy;
// This class is used to run a Mach IPC message server. This server can
// hold the receive right for a bootstrap_port of a process, and it filters
// a subset of the launchd/bootstrap IPC call set for sandboxing. It permits
// or rejects requests based on the per-process policy specified in the
// BootstrapSandbox.
-class LaunchdInterceptionServer {
+class LaunchdInterceptionServer : public MessageDemuxer {
public:
explicit LaunchdInterceptionServer(const BootstrapSandbox* sandbox);
- ~LaunchdInterceptionServer();
+ virtual ~LaunchdInterceptionServer();
// Initializes the class and starts running the message server.
bool Initialize();
- mach_port_t server_port() const { return server_port_.get(); }
+ // MessageDemuxer:
+ virtual void DemuxMessage(mach_msg_header_t* request,
+ mach_msg_header_t* reply) OVERRIDE;
+
+ mach_port_t server_port() const { return message_server_->server_port(); }
private:
- // Event handler for the |server_source_| that reads a message from the queue
- // and processes it.
- void ReceiveMessage();
-
- // Decodes a message header and handles it by either servicing the request
- // itself, forwarding the message on to the real launchd, or rejecting the
- // message with an error.
- void DemuxMessage(mach_msg_header_t* request, mach_msg_header_t* reply);
-
// Given a look_up2 request message, this looks up the appropriate sandbox
// policy for the service name then formulates and sends the reply message.
void HandleLookUp(mach_msg_header_t* request,
mach_msg_header_t* reply,
- pid_t sender_pid);
+ const BootstrapSandboxPolicy* policy);
// Given a swap_integer request message, this verifies that it is safe, and
// if so, forwards it on to launchd for servicing. If the request is unsafe,
// it replies with an error.
void HandleSwapInteger(mach_msg_header_t* request,
- mach_msg_header_t* reply,
- pid_t sender_pid);
-
- // Sends a reply message. Returns true if the message was sent successfully.
- bool SendReply(mach_msg_header_t* reply);
+ mach_msg_header_t* reply);
// Forwards the original |request| on to real bootstrap server for handling.
- void ForwardMessage(mach_msg_header_t* request, mach_msg_header_t* reply);
-
- // Replies to the message with the specified |error_code| as a MIG
- // error_reply RetCode.
- void RejectMessage(mach_msg_header_t* request,
- mach_msg_header_t* reply,
- int error_code);
+ void ForwardMessage(mach_msg_header_t* request);
// The sandbox for which this message server is running.
const BootstrapSandbox* sandbox_;
- // The Mach port on which the server is receiving requests.
- base::mac::ScopedMachReceiveRight server_port_;
-
- // The dispatch queue used to service the server_source_.
- dispatch_queue_t server_queue_;
-
- // A MACH_RECV dispatch source for the server_port_.
- dispatch_source_t server_source_;
-
- // Request and reply buffers used in ReceiveMessage.
- base::mac::ScopedMachVM request_buffer_;
- base::mac::ScopedMachVM reply_buffer_;
-
- // Whether or not ForwardMessage() was called during ReceiveMessage().
- bool did_forward_message_;
+ // The Mach IPC server.
+ scoped_ptr<MachMessageServer> message_server_;
// The Mach port handed out in reply to denied look up requests. All denied
// requests share the same port, though nothing reads messages from it.
diff --git a/sandbox/mac/mach_message_server.cc b/sandbox/mac/mach_message_server.cc
new file mode 100644
index 0000000..9a10121
--- /dev/null
+++ b/sandbox/mac/mach_message_server.cc
@@ -0,0 +1,180 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/mac/mach_message_server.h"
+
+#include <bsm/libbsm.h>
+#include <servers/bootstrap.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/mac/mach_logging.h"
+#include "base/strings/stringprintf.h"
+
+namespace sandbox {
+
+MachMessageServer::MachMessageServer(
+ MessageDemuxer* demuxer,
+ mach_msg_size_t buffer_size)
+ : demuxer_(demuxer),
+ server_port_(MACH_PORT_NULL),
+ server_queue_(NULL),
+ server_source_(NULL),
+ buffer_size_(
+ mach_vm_round_page(buffer_size + sizeof(mach_msg_audit_trailer_t))),
+ did_forward_message_(false) {
+ DCHECK(demuxer_);
+}
+
+MachMessageServer::~MachMessageServer() {
+ if (server_source_)
+ dispatch_release(server_source_);
+ if (server_queue_)
+ dispatch_release(server_queue_);
+}
+
+bool MachMessageServer::Initialize() {
+ mach_port_t task = mach_task_self();
+ kern_return_t kr;
+
+ // Allocate a port for use as a new server port.
+ mach_port_t port;
+ if ((kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &port)) !=
+ KERN_SUCCESS) {
+ MACH_LOG(ERROR, kr) << "Failed to allocate new server port.";
+ return false;
+ }
+ server_port_.reset(port);
+
+ // Allocate the message request and reply buffers.
+ const int kMachMsgMemoryFlags = VM_MAKE_TAG(VM_MEMORY_MACH_MSG) |
+ VM_FLAGS_ANYWHERE;
+ vm_address_t buffer = 0;
+
+ kr = vm_allocate(task, &buffer, buffer_size_, kMachMsgMemoryFlags);
+ if (kr != KERN_SUCCESS) {
+ MACH_LOG(ERROR, kr) << "Failed to allocate request buffer.";
+ return false;
+ }
+ request_buffer_.reset(buffer, buffer_size_);
+
+ kr = vm_allocate(task, &buffer, buffer_size_, kMachMsgMemoryFlags);
+ if (kr != KERN_SUCCESS) {
+ MACH_LOG(ERROR, kr) << "Failed to allocate reply buffer.";
+ return false;
+ }
+ reply_buffer_.reset(buffer, buffer_size_);
+
+ // Set up the dispatch queue to service the bootstrap port.
+ // TODO(rsesek): Specify DISPATCH_QUEUE_SERIAL, in the 10.7 SDK. NULL means
+ // the same thing but is not symbolically clear.
+ std::string label = base::StringPrintf(
+ "org.chromium.sandbox.MachMessageServer.%p", demuxer_);
+ server_queue_ = dispatch_queue_create(label.c_str(), NULL);
+ server_source_ = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV,
+ server_port_.get(), 0, server_queue_);
+ dispatch_source_set_event_handler(server_source_, ^{ ReceiveMessage(); });
+ dispatch_resume(server_source_);
+
+ return true;
+}
+
+pid_t MachMessageServer::GetMessageSenderPID(mach_msg_header_t* request) {
+ // Get the PID of the task that sent this request. This requires getting at
+ // the trailer of the message, from the header.
+ mach_msg_audit_trailer_t* trailer =
+ reinterpret_cast<mach_msg_audit_trailer_t*>(
+ reinterpret_cast<vm_address_t>(request) +
+ round_msg(request->msgh_size));
+ // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
+ pid_t sender_pid;
+ audit_token_to_au32(trailer->msgh_audit,
+ NULL, NULL, NULL, NULL, NULL, &sender_pid, NULL, NULL);
+ return sender_pid;
+}
+
+bool MachMessageServer::SendReply(mach_msg_header_t* reply) {
+ kern_return_t kr = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0,
+ MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr)
+ << "Unable to send intercepted reply message.";
+ return kr == KERN_SUCCESS;
+}
+
+void MachMessageServer::ForwardMessage(mach_msg_header_t* request,
+ mach_port_t destination) {
+ request->msgh_local_port = request->msgh_remote_port;
+ request->msgh_remote_port = destination;
+ // Preserve the msgh_bits that do not deal with the local and remote ports.
+ request->msgh_bits = (request->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
+ MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MOVE_SEND_ONCE);
+ kern_return_t kr = mach_msg_send(request);
+ if (kr == KERN_SUCCESS) {
+ did_forward_message_ = true;
+ } else {
+ MACH_LOG(ERROR, kr) << "Unable to forward message to the real launchd.";
+ }
+}
+
+void MachMessageServer::RejectMessage(mach_msg_header_t* reply,
+ int error_code) {
+ mig_reply_error_t* error_reply = reinterpret_cast<mig_reply_error_t*>(reply);
+ error_reply->Head.msgh_size = sizeof(mig_reply_error_t);
+ error_reply->Head.msgh_bits =
+ MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE);
+ error_reply->NDR = NDR_record;
+ error_reply->RetCode = error_code;
+ SendReply(&error_reply->Head);
+}
+
+void MachMessageServer::ReceiveMessage() {
+ const mach_msg_options_t kRcvOptions = MACH_RCV_MSG |
+ MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
+ MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
+
+ mach_msg_header_t* request =
+ reinterpret_cast<mach_msg_header_t*>(request_buffer_.address());
+ mach_msg_header_t* reply =
+ reinterpret_cast<mach_msg_header_t*>(reply_buffer_.address());
+
+ // Zero out the buffers from handling any previous message.
+ bzero(request, buffer_size_);
+ bzero(reply, buffer_size_);
+ did_forward_message_ = false;
+
+ // A Mach message server-once. The system library to run a message server
+ // cannot be used here, because some requests are conditionally forwarded
+ // to another server.
+ kern_return_t kr = mach_msg(request, kRcvOptions, 0, buffer_size_,
+ server_port_.get(), MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (kr != KERN_SUCCESS) {
+ MACH_LOG(ERROR, kr) << "Unable to receive message.";
+ return;
+ }
+
+ // Set up a reply message in case it will be used.
+ reply->msgh_bits = MACH_MSGH_BITS_REMOTE(reply->msgh_bits);
+ // Since mach_msg will automatically swap the request and reply ports,
+ // undo that.
+ reply->msgh_remote_port = request->msgh_remote_port;
+ reply->msgh_local_port = MACH_PORT_NULL;
+ // MIG servers simply add 100 to the request ID to generate the reply ID.
+ reply->msgh_id = request->msgh_id + 100;
+
+ // Process the message.
+ demuxer_->DemuxMessage(request, reply);
+
+ // Free any descriptors in the message body. If the message was forwarded,
+ // any descriptors would have been moved out of the process on send. If the
+ // forwarded message was sent from the process hosting this sandbox server,
+ // destroying the message could also destroy rights held outside the scope of
+ // this message server.
+ if (!did_forward_message_) {
+ mach_msg_destroy(request);
+ mach_msg_destroy(reply);
+ }
+}
+
+} // namespace sandbox
diff --git a/sandbox/mac/mach_message_server.h b/sandbox/mac/mach_message_server.h
new file mode 100644
index 0000000..f37b4fc
--- /dev/null
+++ b/sandbox/mac/mach_message_server.h
@@ -0,0 +1,88 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_MAC_MACH_MESSAGE_SERVER_H_
+#define SANDBOX_MAC_MACH_MESSAGE_SERVER_H_
+
+#include <dispatch/dispatch.h>
+#include <mach/mach.h>
+
+#include "base/mac/scoped_mach_port.h"
+#include "base/mac/scoped_mach_vm.h"
+
+namespace sandbox {
+
+// A delegate interface for MachMessageServer that handles processing of
+// incoming intercepted IPC messages.
+class MessageDemuxer {
+ public:
+ // Handle a |request| message and optionally create a |reply|. Both message
+ // objects are owned by the server. Use the server's methods to send a
+ // reply message.
+ virtual void DemuxMessage(mach_msg_header_t* request,
+ mach_msg_header_t* reply) = 0;
+
+ protected:
+ virtual ~MessageDemuxer() {}
+};
+
+// A Mach message server that operates a receive port. Messages are received
+// and then passed to the MessageDemuxer for handling. The Demuxer
+// can use the server class to send a reply, forward the message to a
+// different port, or reply to the message with a MIG error.
+class MachMessageServer {
+ public:
+ MachMessageServer(MessageDemuxer* demuxer, mach_msg_size_t buffer_size);
+ ~MachMessageServer();
+
+ // Initializes the class and starts running the message server. If this
+ // returns false, no other methods may be called on this class.
+ bool Initialize();
+
+ // Given a received request message, returns the PID of the sending process.
+ pid_t GetMessageSenderPID(mach_msg_header_t* request);
+
+ // Sends a reply message. Returns true if the message was sent successfully.
+ bool SendReply(mach_msg_header_t* reply);
+
+ // Forwards the original |request| to the |destination| for handling.
+ void ForwardMessage(mach_msg_header_t* request, mach_port_t destination);
+
+ // Replies to the message with the specified |error_code| as a MIG
+ // error_reply RetCode.
+ void RejectMessage(mach_msg_header_t* reply, int error_code);
+
+ mach_port_t server_port() const { return server_port_.get(); }
+
+ private:
+ // Event handler for the |server_source_| that reads a message from the queue
+ // and processes it.
+ void ReceiveMessage();
+
+ // The demuxer delegate. Weak.
+ MessageDemuxer* demuxer_;
+
+ // The Mach port on which the server is receiving requests.
+ base::mac::ScopedMachReceiveRight server_port_;
+
+ // The dispatch queue used to service the server_source_.
+ dispatch_queue_t server_queue_;
+
+ // A MACH_RECV dispatch source for the server_port_.
+ dispatch_source_t server_source_;
+
+ // The size of the two message buffers below.
+ const mach_msg_size_t buffer_size_;
+
+ // Request and reply buffers used in ReceiveMessage.
+ base::mac::ScopedMachVM request_buffer_;
+ base::mac::ScopedMachVM reply_buffer_;
+
+ // Whether or not ForwardMessage() was called during ReceiveMessage().
+ bool did_forward_message_;
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_MAC_MACH_MESSAGE_SERVER_H_
diff --git a/sandbox/mac/os_compatibility.cc b/sandbox/mac/os_compatibility.cc
index be0ca3e..4485006 100644
--- a/sandbox/mac/os_compatibility.cc
+++ b/sandbox/mac/os_compatibility.cc
@@ -112,7 +112,7 @@
shim.look_up2_get_request_name =
&LaunchdLookUp2GetRequestName<look_up2_request_10_6>;
} else if (base::mac::IsOSLionOrLater() &&
- !base::mac::IsOSLaterThanMavericks_DontCallThis()) {
+ !base::mac::IsOSYosemiteOrLater()) {
shim.look_up2_get_request_name =
&LaunchdLookUp2GetRequestName<look_up2_request_10_7>;
} else {
diff --git a/sandbox/mac/sandbox_mac.gypi b/sandbox/mac/sandbox_mac.gypi
index 1824127..36d6901 100644
--- a/sandbox/mac/sandbox_mac.gypi
+++ b/sandbox/mac/sandbox_mac.gypi
@@ -12,16 +12,20 @@
'bootstrap_sandbox.h',
'launchd_interception_server.cc',
'launchd_interception_server.h',
- 'policy.cc',
- 'policy.h',
+ 'mach_message_server.cc',
+ 'mach_message_server.h',
'os_compatibility.cc',
'os_compatibility.h',
+ 'policy.cc',
+ 'policy.h',
+ 'xpc.h',
],
'dependencies': [
'../base/base.gyp:base',
],
'include_dirs': [
'..',
+ '<(SHARED_INTERMEDIATE_DIR)',
],
'defines': [
'SANDBOX_IMPLEMENTATION',
@@ -31,6 +35,43 @@
'$(SDKROOT)/usr/lib/libbsm.dylib',
],
},
+ 'actions': [
+ {
+ 'variables': {
+ 'generate_stubs_script': '../tools/generate_stubs/generate_stubs.py',
+ 'generate_stubs_header_path': 'xpc_stubs_header.fragment',
+ 'generate_stubs_sig_public_path': 'xpc_stubs.sig',
+ 'generate_stubs_sig_private_path': 'xpc_private_stubs.sig',
+ 'generate_stubs_project': 'sandbox/mac',
+ 'generate_stubs_output_stem': 'xpc_stubs',
+ },
+ 'action_name': 'generate_stubs',
+ 'inputs': [
+ '<(generate_stubs_script)',
+ '<(generate_stubs_header_path)',
+ '<(generate_stubs_sig_public_path)',
+ '<(generate_stubs_sig_private_path)',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/<(generate_stubs_output_stem).cc',
+ '<(SHARED_INTERMEDIATE_DIR)/<(generate_stubs_project)/<(generate_stubs_output_stem).h',
+ ],
+ 'action': [
+ 'python',
+ '<(generate_stubs_script)',
+ '-i', '<(INTERMEDIATE_DIR)',
+ '-o', '<(SHARED_INTERMEDIATE_DIR)/<(generate_stubs_project)',
+ '-t', 'posix_stubs',
+ '-e', '<(generate_stubs_header_path)',
+ '-s', '<(generate_stubs_output_stem)',
+ '-p', '<(generate_stubs_project)',
+ '<(generate_stubs_sig_public_path)',
+ '<(generate_stubs_sig_private_path)',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'message': 'Generating XPC stubs for 10.6 compatability.',
+ },
+ ],
},
{
'target_name': 'sandbox_mac_unittests',
diff --git a/sandbox/mac/xpc.h b/sandbox/mac/xpc.h
new file mode 100644
index 0000000..1cbe9ca
--- /dev/null
+++ b/sandbox/mac/xpc.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides forward declarations for XPC symbols that are not
+// present in the 10.6 SDK. It uses generate_stubs to produce code to
+// dynamically load the libxpc.dylib library and set up a stub table, with
+// the same names as the real XPC functions.
+
+#ifndef SANDBOX_MAC_XPC_H_
+#define SANDBOX_MAC_XPC_H_
+
+#include <mach/mach.h>
+
+// C++ library loader.
+#include "sandbox/mac/xpc_stubs.h"
+
+// Declares XPC object types. This includes <xpc/xpc.h> if available.
+#include "sandbox/mac/xpc_stubs_header.fragment"
+
+#if !defined(MAC_OS_X_VERSION_10_7) || \
+ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
+extern "C" {
+// Signatures for XPC public functions that are loaded by xpc_stubs.h.
+#include "sandbox/mac/xpc_stubs.sig"
+// Signatures for private XPC functions.
+#include "sandbox/mac/xpc_private_stubs.sig"
+} // extern "C"
+
+#else
+
+// Signatures for private XPC functions.
+extern "C" {
+#include "sandbox/mac/xpc_private_stubs.sig"
+} // extern "C"
+
+#endif
+
+#endif // SANDBOX_MAC_XPC_H_
diff --git a/sandbox/mac/xpc_private_stubs.sig b/sandbox/mac/xpc_private_stubs.sig
new file mode 100644
index 0000000..33db194
--- /dev/null
+++ b/sandbox/mac/xpc_private_stubs.sig
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains declarations of private XPC functions. This file is
+// used for both forward declarations of private symbols and to use with
+// tools/generate_stubs for creating a dynamic library loader.
+
+// Dictionary manipulation.
+void xpc_dictionary_set_mach_send(xpc_object_t dict, const char* name, mach_port_t port);
+
+// Pipe methods.
+xpc_pipe_t xpc_pipe_create_from_port(mach_port_t port, int flags);
+int xpc_pipe_receive(mach_port_t port, xpc_object_t* message);
+int xpc_pipe_routine(xpc_pipe_t pipe, xpc_object_t request, xpc_object_t* reply);
+int xpc_pipe_routine_reply(xpc_object_t reply);
+int xpc_pipe_routine_forward(xpc_pipe_t forward_to, xpc_object_t request);
diff --git a/sandbox/mac/xpc_stubs.sig b/sandbox/mac/xpc_stubs.sig
new file mode 100644
index 0000000..5020ffd
--- /dev/null
+++ b/sandbox/mac/xpc_stubs.sig
@@ -0,0 +1,16 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains declarations of public XPC functions used in the sandbox.
+// This file is used with tools/generate_stubs for creating a dynamic library
+// loader.
+
+// XPC object management.
+void xpc_release(xpc_object_t object);
+
+// Dictionary manipulation.
+const char* xpc_dictionary_get_string(xpc_object_t dictionary, const char* key);
+uint64_t xpc_dictionary_get_uint64(xpc_object_t dictionary, const char* key);
+void xpc_dictionary_set_int64(xpc_object_t dictionary, const char* key, int64_t value);
+xpc_object_t xpc_dictionary_create_reply(xpc_object_t request);
diff --git a/sandbox/mac/xpc_stubs_header.fragment b/sandbox/mac/xpc_stubs_header.fragment
new file mode 100644
index 0000000..a29907e
--- /dev/null
+++ b/sandbox/mac/xpc_stubs_header.fragment
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_MAC_XPC_STUBS_HEADER_FRAGMENT_
+#define SANDBOX_MAC_XPC_STUBS_HEADER_FRAGMENT_
+
+// Declare or include public types.
+#if !defined(MAC_OS_X_VERSION_10_7) || \
+ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+
+extern "C" {
+typedef void* xpc_object_t;
+} // extern "C"
+
+#else
+
+#include <xpc/xpc.h>
+
+#endif
+
+// Declare private types.
+extern "C" {
+typedef struct _xpc_pipe_s* xpc_pipe_t;
+} // extern "C"
+
+#endif // SANDBOX_MAC_XPC_STUBS_HEADER_FRAGMENT_
diff --git a/sandbox/sandbox_services.target.darwin-arm.mk b/sandbox/sandbox_services.target.darwin-arm.mk
index f079c1d..0148b53 100644
--- a/sandbox/sandbox_services.target.darwin-arm.mk
+++ b/sandbox/sandbox_services.target.darwin-arm.mk
@@ -82,6 +82,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -112,6 +113,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -181,6 +183,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -212,6 +215,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.darwin-arm64.mk b/sandbox/sandbox_services.target.darwin-arm64.mk
index 6337b1b..ce59907 100644
--- a/sandbox/sandbox_services.target.darwin-arm64.mk
+++ b/sandbox/sandbox_services.target.darwin-arm64.mk
@@ -72,6 +72,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -102,6 +103,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -160,6 +162,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -191,6 +194,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.darwin-mips.mk b/sandbox/sandbox_services.target.darwin-mips.mk
index f188c24..c92d333 100644
--- a/sandbox/sandbox_services.target.darwin-mips.mk
+++ b/sandbox/sandbox_services.target.darwin-mips.mk
@@ -76,6 +76,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -106,6 +107,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -169,6 +171,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -200,6 +203,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.darwin-x86.mk b/sandbox/sandbox_services.target.darwin-x86.mk
index 9dcce10..330bd65 100644
--- a/sandbox/sandbox_services.target.darwin-x86.mk
+++ b/sandbox/sandbox_services.target.darwin-x86.mk
@@ -77,6 +77,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -107,6 +108,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -170,6 +172,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -201,6 +204,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.darwin-x86_64.mk b/sandbox/sandbox_services.target.darwin-x86_64.mk
index 6d20bbd..525a2af 100644
--- a/sandbox/sandbox_services.target.darwin-x86_64.mk
+++ b/sandbox/sandbox_services.target.darwin-x86_64.mk
@@ -76,6 +76,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -106,6 +107,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -168,6 +170,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -199,6 +202,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.linux-arm.mk b/sandbox/sandbox_services.target.linux-arm.mk
index f079c1d..0148b53 100644
--- a/sandbox/sandbox_services.target.linux-arm.mk
+++ b/sandbox/sandbox_services.target.linux-arm.mk
@@ -82,6 +82,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -112,6 +113,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -181,6 +183,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -212,6 +215,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.linux-arm64.mk b/sandbox/sandbox_services.target.linux-arm64.mk
index 6337b1b..ce59907 100644
--- a/sandbox/sandbox_services.target.linux-arm64.mk
+++ b/sandbox/sandbox_services.target.linux-arm64.mk
@@ -72,6 +72,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -102,6 +103,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -160,6 +162,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -191,6 +194,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.linux-mips.mk b/sandbox/sandbox_services.target.linux-mips.mk
index f188c24..c92d333 100644
--- a/sandbox/sandbox_services.target.linux-mips.mk
+++ b/sandbox/sandbox_services.target.linux-mips.mk
@@ -76,6 +76,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -106,6 +107,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -169,6 +171,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -200,6 +203,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.linux-x86.mk b/sandbox/sandbox_services.target.linux-x86.mk
index 9dcce10..330bd65 100644
--- a/sandbox/sandbox_services.target.linux-x86.mk
+++ b/sandbox/sandbox_services.target.linux-x86.mk
@@ -77,6 +77,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -107,6 +108,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -170,6 +172,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -201,6 +204,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services.target.linux-x86_64.mk b/sandbox/sandbox_services.target.linux-x86_64.mk
index 6d20bbd..525a2af 100644
--- a/sandbox/sandbox_services.target.linux-x86_64.mk
+++ b/sandbox/sandbox_services.target.linux-x86_64.mk
@@ -76,6 +76,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -106,6 +107,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
@@ -168,6 +170,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -199,6 +202,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
diff --git a/sandbox/sandbox_services_headers.target.darwin-arm.mk b/sandbox/sandbox_services_headers.target.darwin-arm.mk
index eb6a359..5c53c90 100644
--- a/sandbox/sandbox_services_headers.target.darwin-arm.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-arm.mk
@@ -77,6 +77,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -105,6 +106,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -173,6 +175,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -202,6 +205,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/sandbox_services_headers.target.darwin-x86.mk b/sandbox/sandbox_services_headers.target.darwin-x86.mk
index 71f95e4..4ed441e 100644
--- a/sandbox/sandbox_services_headers.target.darwin-x86.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-x86.mk
@@ -72,6 +72,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -100,6 +101,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -162,6 +164,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -191,6 +194,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/sandbox_services_headers.target.darwin-x86_64.mk b/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
index 80a1ea1..ab9b686 100644
--- a/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
@@ -71,6 +71,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -99,6 +100,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -160,6 +162,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -189,6 +192,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/sandbox_services_headers.target.linux-arm.mk b/sandbox/sandbox_services_headers.target.linux-arm.mk
index eb6a359..5c53c90 100644
--- a/sandbox/sandbox_services_headers.target.linux-arm.mk
+++ b/sandbox/sandbox_services_headers.target.linux-arm.mk
@@ -77,6 +77,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -105,6 +106,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -173,6 +175,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -202,6 +205,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/sandbox_services_headers.target.linux-x86.mk b/sandbox/sandbox_services_headers.target.linux-x86.mk
index 71f95e4..4ed441e 100644
--- a/sandbox/sandbox_services_headers.target.linux-x86.mk
+++ b/sandbox/sandbox_services_headers.target.linux-x86.mk
@@ -72,6 +72,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -100,6 +101,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -162,6 +164,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -191,6 +194,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/sandbox_services_headers.target.linux-x86_64.mk b/sandbox/sandbox_services_headers.target.linux-x86_64.mk
index 80a1ea1..ab9b686 100644
--- a/sandbox/sandbox_services_headers.target.linux-x86_64.mk
+++ b/sandbox/sandbox_services_headers.target.linux-x86_64.mk
@@ -71,6 +71,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -99,6 +100,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -160,6 +162,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -189,6 +192,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH)/sandbox \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf.target.darwin-arm.mk b/sandbox/seccomp_bpf.target.darwin-arm.mk
index 42ca308..044e15f 100644
--- a/sandbox/seccomp_bpf.target.darwin-arm.mk
+++ b/sandbox/seccomp_bpf.target.darwin-arm.mk
@@ -88,6 +88,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -118,6 +119,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -186,6 +188,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -217,6 +220,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf.target.darwin-x86.mk b/sandbox/seccomp_bpf.target.darwin-x86.mk
index f807852..00e9eb4 100644
--- a/sandbox/seccomp_bpf.target.darwin-x86.mk
+++ b/sandbox/seccomp_bpf.target.darwin-x86.mk
@@ -83,6 +83,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -113,6 +114,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -175,6 +177,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -206,6 +209,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf.target.darwin-x86_64.mk b/sandbox/seccomp_bpf.target.darwin-x86_64.mk
index 69676fc..67372ef 100644
--- a/sandbox/seccomp_bpf.target.darwin-x86_64.mk
+++ b/sandbox/seccomp_bpf.target.darwin-x86_64.mk
@@ -82,6 +82,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -112,6 +113,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -173,6 +175,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -204,6 +207,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf.target.linux-arm.mk b/sandbox/seccomp_bpf.target.linux-arm.mk
index 42ca308..044e15f 100644
--- a/sandbox/seccomp_bpf.target.linux-arm.mk
+++ b/sandbox/seccomp_bpf.target.linux-arm.mk
@@ -88,6 +88,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -118,6 +119,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -186,6 +188,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -217,6 +220,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf.target.linux-x86.mk b/sandbox/seccomp_bpf.target.linux-x86.mk
index f807852..00e9eb4 100644
--- a/sandbox/seccomp_bpf.target.linux-x86.mk
+++ b/sandbox/seccomp_bpf.target.linux-x86.mk
@@ -83,6 +83,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -113,6 +114,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -175,6 +177,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -206,6 +209,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf.target.linux-x86_64.mk b/sandbox/seccomp_bpf.target.linux-x86_64.mk
index 69676fc..67372ef 100644
--- a/sandbox/seccomp_bpf.target.linux-x86_64.mk
+++ b/sandbox/seccomp_bpf.target.linux-x86_64.mk
@@ -82,6 +82,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -112,6 +113,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -173,6 +175,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -204,6 +207,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk b/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
index fb443a5..93273e3 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
@@ -81,6 +81,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -111,6 +112,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -179,6 +181,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -210,6 +213,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk b/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
index c6e2225..568602d 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
@@ -76,6 +76,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -106,6 +107,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -168,6 +170,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -199,6 +202,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk b/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
index d442273..436c507 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
@@ -75,6 +75,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -105,6 +106,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -166,6 +168,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -197,6 +200,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-arm.mk b/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
index fb443a5..93273e3 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
@@ -81,6 +81,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -111,6 +112,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -179,6 +181,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -210,6 +213,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-x86.mk b/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
index c6e2225..568602d 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
@@ -76,6 +76,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -106,6 +107,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -168,6 +170,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -199,6 +202,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk b/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
index d442273..436c507 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
@@ -75,6 +75,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -105,6 +106,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Debug := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
@@ -166,6 +168,7 @@
'-DUSE_LIBJPEG_TURBO=1' \
'-DENABLE_WEBRTC=1' \
'-DUSE_PROPRIETARY_CODECS' \
+ '-DENABLE_BROWSER_CDMS' \
'-DENABLE_CONFIGURATION_POLICY' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
@@ -197,6 +200,7 @@
# Include paths placed before CFLAGS/CPPFLAGS
LOCAL_C_INCLUDES_Release := \
$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+ $(gyp_shared_intermediate_dir) \
$(LOCAL_PATH) \
$(PWD)/frameworks/wilhelm/include \
$(PWD)/bionic \
diff --git a/sandbox/win/sandbox_win.gypi b/sandbox/win/sandbox_win.gypi
index 42644bc..7d9cf94 100644
--- a/sandbox/win/sandbox_win.gypi
+++ b/sandbox/win/sandbox_win.gypi
@@ -74,6 +74,12 @@
'src/policy_target.h',
'src/process_mitigations.cc',
'src/process_mitigations.h',
+ 'src/process_mitigations_win32k_dispatcher.cc',
+ 'src/process_mitigations_win32k_dispatcher.h',
+ 'src/process_mitigations_win32k_interception.cc',
+ 'src/process_mitigations_win32k_interception.h',
+ 'src/process_mitigations_win32k_policy.cc',
+ 'src/process_mitigations_win32k_policy.h',
'src/process_thread_dispatcher.cc',
'src/process_thread_dispatcher.h',
'src/process_thread_interception.cc',
@@ -208,6 +214,7 @@
'type': 'executable',
'dependencies': [
'sandbox',
+ '../base/base.gyp:test_support_base',
'../testing/gtest.gyp:gtest',
],
'sources': [
@@ -239,6 +246,7 @@
'type': 'executable',
'dependencies': [
'sandbox',
+ '../base/base.gyp:test_support_base',
'../testing/gtest.gyp:gtest',
],
'sources': [
@@ -255,6 +263,7 @@
'type': 'executable',
'dependencies': [
'sandbox',
+ '../base/base.gyp:test_support_base',
'../testing/gtest.gyp:gtest',
],
'sources': [
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc
index 2350342..895d535 100644
--- a/sandbox/win/src/broker_services.cc
+++ b/sandbox/win/src/broker_services.cc
@@ -278,6 +278,13 @@
break;
}
+ case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: {
+ BOOL res = ::TerminateJobObject(tracker->job,
+ SBOX_FATAL_MEMORY_EXCEEDED);
+ DCHECK(res);
+ break;
+ }
+
default: {
NOTREACHED();
break;
diff --git a/sandbox/win/src/crosscall_server.cc b/sandbox/win/src/crosscall_server.cc
index ab8b421..65a9084 100644
--- a/sandbox/win/src/crosscall_server.cc
+++ b/sandbox/win/src/crosscall_server.cc
@@ -60,7 +60,6 @@
case 9:
return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
default:
- NOTREACHED();
return 0;
}
}
diff --git a/sandbox/win/src/handle_closer.cc b/sandbox/win/src/handle_closer.cc
index d250ec3..30e8977 100644
--- a/sandbox/win/src/handle_closer.cc
+++ b/sandbox/win/src/handle_closer.cc
@@ -154,27 +154,6 @@
return output <= end;
}
-bool HandleCloser::SetupHandleInterceptions(InterceptionManager* manager) {
- // We need to intercept CreateThread if we're closing ALPC port clients.
- HandleMap::iterator names = handles_to_close_.find(L"ALPC Port");
- if (base::win::GetVersion() >= base::win::VERSION_VISTA &&
- names != handles_to_close_.end() &&
- (names->second.empty() || names->second.size() == 0)) {
- if (!INTERCEPT_EAT(manager, kKerneldllName, CreateThread,
- CREATE_THREAD_ID, 28)) {
- return false;
- }
- if (!INTERCEPT_EAT(manager, kKerneldllName, GetUserDefaultLCID,
- GET_USER_DEFAULT_LCID_ID, 4)) {
- return false;
- }
-
- return true;
- }
-
- return true;
-}
-
bool GetHandleName(HANDLE handle, base::string16* handle_name) {
static NtQueryObject QueryObject = NULL;
if (!QueryObject)
diff --git a/sandbox/win/src/handle_closer.h b/sandbox/win/src/handle_closer.h
index a5808d1..60473b3 100644
--- a/sandbox/win/src/handle_closer.h
+++ b/sandbox/win/src/handle_closer.h
@@ -53,9 +53,6 @@
// Serializes and copies the closer table into the target process.
bool InitializeTargetHandles(TargetProcess* target);
- // Adds any interceptions that may be required due to closed system handles.
- bool SetupHandleInterceptions(InterceptionManager* manager);
-
private:
// Calculates the memory needed to copy the serialized handles list (rounded
// to the nearest machine-word size).
diff --git a/sandbox/win/src/interceptors.h b/sandbox/win/src/interceptors.h
index 43126d0..a17447a 100644
--- a/sandbox/win/src/interceptors.h
+++ b/sandbox/win/src/interceptors.h
@@ -41,9 +41,10 @@
// Sync dispatcher:
CREATE_EVENT_ID,
OPEN_EVENT_ID,
- // CSRSS bypasses for HandleCloser:
- CREATE_THREAD_ID,
- GET_USER_DEFAULT_LCID_ID,
+ // Process mitigations Win32k dispatcher:
+ GDIINITIALIZE_ID,
+ GETSTOCKOBJECT_ID,
+ REGISTERCLASSW_ID,
INTERCEPTOR_MAX_ID
};
diff --git a/sandbox/win/src/interceptors_64.cc b/sandbox/win/src/interceptors_64.cc
index c71d5a2..ef0b5f0 100644
--- a/sandbox/win/src/interceptors_64.cc
+++ b/sandbox/win/src/interceptors_64.cc
@@ -8,6 +8,7 @@
#include "sandbox/win/src/filesystem_interception.h"
#include "sandbox/win/src/named_pipe_interception.h"
#include "sandbox/win/src/policy_target.h"
+#include "sandbox/win/src/process_mitigations_win32k_interception.h"
#include "sandbox/win/src/process_thread_interception.h"
#include "sandbox/win/src/registry_interception.h"
#include "sandbox/win/src/sandbox_nt_types.h"
@@ -68,23 +69,6 @@
open_as_self, handle_attributes, token);
}
-HANDLE WINAPI TargetCreateThread64(
- LPSECURITY_ATTRIBUTES thread_attributes, SIZE_T stack_size,
- LPTHREAD_START_ROUTINE start_address, PVOID parameter, DWORD creation_flags,
- LPDWORD thread_id) {
- CreateThreadFunction orig_fn = reinterpret_cast<
- CreateThreadFunction>(g_originals[CREATE_THREAD_ID]);
- return TargetCreateThread(orig_fn, thread_attributes, stack_size,
- start_address, parameter, creation_flags,
- thread_id);
-}
-
-LCID WINAPI TargetGetUserDefaultLCID64(void) {
- GetUserDefaultLCIDFunction orig_fn = reinterpret_cast<
- GetUserDefaultLCIDFunction>(g_originals[GET_USER_DEFAULT_LCID_ID]);
- return TargetGetUserDefaultLCID(orig_fn);
-}
-
// -----------------------------------------------------------------------
SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateFile64(
@@ -268,4 +252,27 @@
object_attributes);
}
+// -----------------------------------------------------------------------
+
+SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize64(
+ HANDLE dll,
+ DWORD reason) {
+ GdiDllInitializeFunction orig_fn = reinterpret_cast<
+ GdiDllInitializeFunction>(g_originals[GDIINITIALIZE_ID]);
+ return TargetGdiDllInitialize(orig_fn, dll, reason);
+}
+
+SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject64(int object) {
+ GetStockObjectFunction orig_fn = reinterpret_cast<
+ GetStockObjectFunction>(g_originals[GETSTOCKOBJECT_ID]);
+ return TargetGetStockObject(orig_fn, object);
+}
+
+SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW64(
+ const WNDCLASS* wnd_class) {
+ RegisterClassWFunction orig_fn = reinterpret_cast<
+ RegisterClassWFunction>(g_originals[REGISTERCLASSW_ID]);
+ return TargetRegisterClassW(orig_fn, wnd_class);
+}
+
} // namespace sandbox
diff --git a/sandbox/win/src/interceptors_64.h b/sandbox/win/src/interceptors_64.h
index ef2c10d..7368ceb 100644
--- a/sandbox/win/src/interceptors_64.h
+++ b/sandbox/win/src/interceptors_64.h
@@ -44,15 +44,6 @@
HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self,
ULONG handle_attributes, PHANDLE token);
-// Interception of CreateThread on the child process.
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateThread64(
- LPSECURITY_ATTRIBUTES thread_attributes, SIZE_T stack_size,
- LPTHREAD_START_ROUTINE start_address, PVOID parameter,
- DWORD creation_flags, LPDWORD thread_id);
-
-// Interception of GetUserDefaultLCID on the child process.
-SANDBOX_INTERCEPT LCID WINAPI TargetGetUserDefaultLCID64();
-
// -----------------------------------------------------------------------
// Interceptors handled by the file system dispatcher.
@@ -163,6 +154,20 @@
PHANDLE event_handle, ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes);
+// -----------------------------------------------------------------------
+// Interceptors handled by the process mitigations win32k lockdown code.
+
+// Interceptor for the GdiDllInitialize function.
+SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize64(
+ HANDLE dll,
+ DWORD reason);
+
+// Interceptor for the GetStockObject function.
+SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject64(int object);
+
+// Interceptor for the RegisterClassW function.
+SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW64(const WNDCLASS* wnd_class);
+
} // extern "C"
} // namespace sandbox
diff --git a/sandbox/win/src/ipc_tags.h b/sandbox/win/src/ipc_tags.h
index 4e3a806..d680411 100644
--- a/sandbox/win/src/ipc_tags.h
+++ b/sandbox/win/src/ipc_tags.h
@@ -29,6 +29,9 @@
IPC_NTCREATEKEY_TAG,
IPC_NTOPENKEY_TAG,
IPC_DUPLICATEHANDLEPROXY_TAG,
+ IPC_GDI_GDIDLLINITIALIZE_TAG,
+ IPC_GDI_GETSTOCKOBJECT_TAG,
+ IPC_USER_REGISTERCLASSW_TAG,
IPC_LAST_TAG
};
diff --git a/sandbox/win/src/ipc_unittest.cc b/sandbox/win/src/ipc_unittest.cc
index 612ab84..7bdd286 100644
--- a/sandbox/win/src/ipc_unittest.cc
+++ b/sandbox/win/src/ipc_unittest.cc
@@ -315,8 +315,7 @@
EXPECT_EQ(1, ccp->GetParamsCount());
delete[] (reinterpret_cast<char*>(ccp));
-#if defined(NDEBUG)
- // Test hat we handle integer overflow on the number of params
+ // Test that we handle integer overflow on the number of params
// correctly. We use a test-only ctor for ActualCallParams that
// allows to create malformed cross-call buffers.
const int32 kPtrDiffSz = sizeof(ptrdiff_t);
@@ -332,7 +331,6 @@
// If the buffer is malformed the return is NULL.
EXPECT_TRUE(NULL == ccp);
}
-#endif // defined(NDEBUG)
ActualCallParams<1, kBufferSize> params_3(kTag, 1);
params_3.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
diff --git a/sandbox/win/src/job.cc b/sandbox/win/src/job.cc
index 62b8d5c..8852ab0 100644
--- a/sandbox/win/src/job.cc
+++ b/sandbox/win/src/job.cc
@@ -16,7 +16,8 @@
DWORD Job::Init(JobLevel security_level,
const wchar_t* job_name,
- DWORD ui_exceptions) {
+ DWORD ui_exceptions,
+ size_t memory_limit) {
if (job_handle_)
return ERROR_ALREADY_INITIALIZED;
@@ -52,11 +53,11 @@
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
}
case JOB_UNPROTECTED: {
- // The JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag is not supported on
- // Windows 2000. We need a mechanism on Windows 2000 to ensure
- // that processes in the job are terminated when the job is closed
- if (base::win::GetVersion() == base::win::VERSION_PRE_XP)
- break;
+ if (memory_limit) {
+ jeli.BasicLimitInformation.LimitFlags |=
+ JOB_OBJECT_LIMIT_PROCESS_MEMORY;
+ jeli.ProcessMemoryLimit = memory_limit;
+ }
jeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
diff --git a/sandbox/win/src/job.h b/sandbox/win/src/job.h
index 7c215ef..60dc314 100644
--- a/sandbox/win/src/job.h
+++ b/sandbox/win/src/job.h
@@ -31,7 +31,8 @@
// the error.
DWORD Init(JobLevel security_level,
const wchar_t* job_name,
- DWORD ui_exceptions);
+ DWORD ui_exceptions,
+ size_t memory_limit);
// Assigns the process referenced by process_handle to the job.
// If the function succeeds, the return value is ERROR_SUCCESS. If the
diff --git a/sandbox/win/src/job_unittest.cc b/sandbox/win/src/job_unittest.cc
index 3b2b331..a1b7aca 100644
--- a/sandbox/win/src/job_unittest.cc
+++ b/sandbox/win/src/job_unittest.cc
@@ -16,7 +16,7 @@
{
// Create the job.
Job job;
- ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0));
// check if the job exists.
HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE,
@@ -40,7 +40,7 @@
{
// Create the job.
Job job;
- ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0));
job_handle = job.Detach();
ASSERT_TRUE(job_handle != NULL);
@@ -73,7 +73,7 @@
// Create the job.
Job job;
ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name",
- JOB_OBJECT_UILIMIT_READCLIPBOARD));
+ JOB_OBJECT_UILIMIT_READCLIPBOARD, 0));
job_handle = job.Detach();
ASSERT_TRUE(job_handle != NULL);
@@ -93,7 +93,7 @@
{
// Create the job.
Job job;
- ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0));
job_handle = job.Detach();
ASSERT_TRUE(job_handle != NULL);
@@ -115,8 +115,8 @@
TEST(JobTest, DoubleInit) {
// Create the job.
Job job;
- ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0));
- ASSERT_EQ(ERROR_ALREADY_INITIALIZED, job.Init(JOB_LOCKDOWN, L"test", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0));
+ ASSERT_EQ(ERROR_ALREADY_INITIALIZED, job.Init(JOB_LOCKDOWN, L"test", 0, 0));
}
// Tests the error case when we use a method and the object is not yet
@@ -131,34 +131,35 @@
// Tests the initialization of the job with different security level.
TEST(JobTest, SecurityLevel) {
Job job1;
- ASSERT_EQ(ERROR_SUCCESS, job1.Init(JOB_LOCKDOWN, L"job1", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job1.Init(JOB_LOCKDOWN, L"job1", 0, 0));
Job job2;
- ASSERT_EQ(ERROR_SUCCESS, job2.Init(JOB_RESTRICTED, L"job2", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job2.Init(JOB_RESTRICTED, L"job2", 0, 0));
Job job3;
- ASSERT_EQ(ERROR_SUCCESS, job3.Init(JOB_LIMITED_USER, L"job3", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job3.Init(JOB_LIMITED_USER, L"job3", 0, 0));
Job job4;
- ASSERT_EQ(ERROR_SUCCESS, job4.Init(JOB_INTERACTIVE, L"job4", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job4.Init(JOB_INTERACTIVE, L"job4", 0, 0));
Job job5;
- ASSERT_EQ(ERROR_SUCCESS, job5.Init(JOB_UNPROTECTED, L"job5", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job5.Init(JOB_UNPROTECTED, L"job5", 0, 0));
// JOB_NONE means we run without a job object so Init should fail.
Job job6;
- ASSERT_EQ(ERROR_BAD_ARGUMENTS, job6.Init(JOB_NONE, L"job6", 0));
+ ASSERT_EQ(ERROR_BAD_ARGUMENTS, job6.Init(JOB_NONE, L"job6", 0, 0));
Job job7;
ASSERT_EQ(ERROR_BAD_ARGUMENTS, job7.Init(
- static_cast<JobLevel>(JOB_NONE+1), L"job7", 0));
+ static_cast<JobLevel>(JOB_NONE+1), L"job7", 0, 0));
}
// Tests the method "AssignProcessToJob".
TEST(JobTest, ProcessInJob) {
// Create the job.
Job job;
- ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_UNPROTECTED, L"job_test_process", 0));
+ ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_UNPROTECTED, L"job_test_process", 0,
+ 0));
BOOL result = FALSE;
diff --git a/sandbox/win/src/process_mitigations_test.cc b/sandbox/win/src/process_mitigations_test.cc
index 19e55ba..e606256 100644
--- a/sandbox/win/src/process_mitigations_test.cc
+++ b/sandbox/win/src/process_mitigations_test.cc
@@ -88,7 +88,6 @@
reinterpret_cast<GetProcessMitigationPolicyFunction>(
::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"),
"GetProcessMitigationPolicy"));
-
if (!get_process_mitigation_policy)
return SBOX_TEST_NOT_FOUND;
@@ -103,9 +102,6 @@
if (!CheckWin8StrictHandlePolicy())
return SBOX_TEST_THIRD_ERROR;
- if (!CheckWin8Win32CallPolicy())
- return SBOX_TEST_FOURTH_ERROR;
-
if (!CheckWin8DllExtensionPolicy())
return SBOX_TEST_FIFTH_ERROR;
@@ -201,5 +197,52 @@
}
#endif
+SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t **argv) {
+ get_process_mitigation_policy =
+ reinterpret_cast<GetProcessMitigationPolicyFunction>(
+ ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"),
+ "GetProcessMitigationPolicy"));
+ if (!get_process_mitigation_policy)
+ return SBOX_TEST_NOT_FOUND;
+
+ if (!CheckWin8Win32CallPolicy())
+ return SBOX_TEST_FIRST_ERROR;
+ return SBOX_TEST_SUCCEEDED;
+}
+
+// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation on
+// the target process causes the launch to fail in process initialization.
+// The test process itself links against user32/gdi32.
+TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownFailure) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+
+ TestRunner runner;
+ sandbox::TargetPolicy* policy = runner.GetPolicy();
+
+ EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE),
+ SBOX_ALL_OK);
+ EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown"));
+}
+
+// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation
+// along with the policy to fake user32 and gdi32 initialization successfully
+// launches the target process.
+// The test process itself links against user32/gdi32.
+TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownSuccess) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+
+ TestRunner runner;
+ sandbox::TargetPolicy* policy = runner.GetPolicy();
+
+ EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE),
+ SBOX_ALL_OK);
+ EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN,
+ sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL),
+ sandbox::SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown"));
+}
+
} // namespace sandbox
diff --git a/sandbox/win/src/process_mitigations_win32k_dispatcher.cc b/sandbox/win/src/process_mitigations_win32k_dispatcher.cc
new file mode 100644
index 0000000..e426084
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_win32k_dispatcher.cc
@@ -0,0 +1,57 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
+#include "sandbox/win/src/interception.h"
+#include "sandbox/win/src/interceptors.h"
+#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/process_mitigations_win32k_interception.h"
+
+namespace sandbox {
+
+ProcessMitigationsWin32KDispatcher::ProcessMitigationsWin32KDispatcher(
+ PolicyBase* policy_base)
+ : policy_base_(policy_base) {
+}
+
+bool ProcessMitigationsWin32KDispatcher::SetupService(
+ InterceptionManager* manager, int service) {
+ if (!(policy_base_->GetProcessMitigations() &
+ sandbox::MITIGATION_WIN32K_DISABLE)) {
+ return false;
+ }
+
+ switch (service) {
+ case IPC_GDI_GDIDLLINITIALIZE_TAG: {
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GdiDllInitialize,
+ GDIINITIALIZE_ID, 12)) {
+ return false;
+ }
+ return true;
+ }
+
+ case IPC_GDI_GETSTOCKOBJECT_TAG: {
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetStockObject,
+ GETSTOCKOBJECT_ID, 8)) {
+ return false;
+ }
+ return true;
+ }
+
+ case IPC_USER_REGISTERCLASSW_TAG: {
+ if (!INTERCEPT_EAT(manager, L"user32.dll", RegisterClassW,
+ REGISTERCLASSW_ID, 8)) {
+ return false;
+ }
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+} // namespace sandbox
+
diff --git a/sandbox/win/src/process_mitigations_win32k_dispatcher.h b/sandbox/win/src/process_mitigations_win32k_dispatcher.h
new file mode 100644
index 0000000..65c9f77
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_win32k_dispatcher.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_
+#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_
+
+#include "base/basictypes.h"
+#include "sandbox/win/src/sandbox_policy_base.h"
+
+namespace sandbox {
+
+// This class sets up intercepts for the Win32K lockdown policy which is set
+// on Windows 8 and beyond.
+class ProcessMitigationsWin32KDispatcher : public Dispatcher {
+ public:
+ explicit ProcessMitigationsWin32KDispatcher(PolicyBase* policy_base);
+ ~ProcessMitigationsWin32KDispatcher() {}
+
+ // Dispatcher interface.
+ virtual bool SetupService(InterceptionManager* manager, int service);
+
+ private:
+ PolicyBase* policy_base_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessMitigationsWin32KDispatcher);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_
diff --git a/sandbox/win/src/process_mitigations_win32k_interception.cc b/sandbox/win/src/process_mitigations_win32k_interception.cc
new file mode 100644
index 0000000..ee24fbf
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_win32k_interception.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/src/process_mitigations_win32k_interception.h"
+
+namespace sandbox {
+
+BOOL WINAPI TargetGdiDllInitialize(
+ GdiDllInitializeFunction orig_gdi_dll_initialize,
+ HANDLE dll,
+ DWORD reason) {
+ return TRUE;
+}
+
+HGDIOBJ WINAPI TargetGetStockObject(
+ GetStockObjectFunction orig_get_stock_object,
+ int object) {
+ return reinterpret_cast<HGDIOBJ>(NULL);
+}
+
+ATOM WINAPI TargetRegisterClassW(
+ RegisterClassWFunction orig_register_class_function,
+ const WNDCLASS* wnd_class) {
+ return TRUE;
+}
+
+} // namespace sandbox
+
diff --git a/sandbox/win/src/process_mitigations_win32k_interception.h b/sandbox/win/src/process_mitigations_win32k_interception.h
new file mode 100644
index 0000000..bf7b551
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_win32k_interception.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_
+#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_
+
+#include <windows.h>
+#include "base/basictypes.h"
+#include "sandbox/win/src/sandbox_types.h"
+
+namespace sandbox {
+
+extern "C" {
+
+typedef BOOL (WINAPI* GdiDllInitializeFunction) (
+ HANDLE dll,
+ DWORD reason,
+ LPVOID reserved);
+
+typedef HGDIOBJ (WINAPI *GetStockObjectFunction) (int object);
+
+typedef ATOM (WINAPI *RegisterClassWFunction) (const WNDCLASS* wnd_class);
+
+// Interceptor for the GdiDllInitialize function.
+SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize(
+ GdiDllInitializeFunction orig_gdi_dll_initialize,
+ HANDLE dll,
+ DWORD reason);
+
+// Interceptor for the GetStockObject function.
+SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject(
+ GetStockObjectFunction orig_get_stock_object,
+ int object);
+
+// Interceptor for the RegisterClassW function.
+SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW(
+ RegisterClassWFunction orig_register_class_function,
+ const WNDCLASS* wnd_class);
+
+} // extern "C"
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_
+
diff --git a/sandbox/win/src/process_mitigations_win32k_policy.cc b/sandbox/win/src/process_mitigations_win32k_policy.cc
new file mode 100644
index 0000000..af18c54
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_win32k_policy.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sandbox/win/src/process_mitigations_win32k_policy.h"
+
+namespace sandbox {
+
+bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
+ const wchar_t* name,
+ TargetPolicy::Semantics semantics,
+ LowLevelPolicy* policy) {
+ PolicyRule rule(FAKE_SUCCESS);
+ if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule))
+ return false;
+ if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule))
+ return false;
+ if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule))
+ return false;
+ return true;
+}
+
+} // namespace sandbox
+
diff --git a/sandbox/win/src/process_mitigations_win32k_policy.h b/sandbox/win/src/process_mitigations_win32k_policy.h
new file mode 100644
index 0000000..078ed2b
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_win32k_policy.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_
+#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_
+
+#include "base/basictypes.h"
+#include "sandbox/win/src/crosscall_server.h"
+#include "sandbox/win/src/policy_low_level.h"
+#include "sandbox/win/src/sandbox_policy.h"
+
+namespace sandbox {
+
+enum EvalResult;
+
+// This class centralizes most of the knowledge related to the process
+// mitigations Win32K lockdown policy.
+class ProcessMitigationsWin32KLockdownPolicy {
+ public:
+ // Creates the required low-level policy rules to evaluate a high-level
+ // policy rule for the Win32K process mitigation policy.
+ // name is the object name, semantics is the desired semantics for the
+ // open or create and policy is the policy generator to which the rules are
+ // going to be added.
+ static bool GenerateRules(const wchar_t* name,
+ TargetPolicy::Semantics semantics,
+ LowLevelPolicy* policy);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_
+
+
diff --git a/sandbox/win/src/process_thread_interception.cc b/sandbox/win/src/process_thread_interception.cc
index d351ee5..45926bc 100644
--- a/sandbox/win/src/process_thread_interception.cc
+++ b/sandbox/win/src/process_thread_interception.cc
@@ -400,50 +400,4 @@
return FALSE;
}
-// Creates a thread without registering with CSRSS. This is required if we
-// closed the CSRSS ALPC port after lockdown.
-HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread,
- LPSECURITY_ATTRIBUTES thread_attributes,
- SIZE_T stack_size,
- LPTHREAD_START_ROUTINE start_address,
- PVOID parameter,
- DWORD creation_flags,
- LPDWORD thread_id) {
-// Try the normal CreateThread; switch to RtlCreateUserThread if needed.
- static bool use_create_thread = true;
- HANDLE thread;
- if (use_create_thread) {
- thread = orig_CreateThread(thread_attributes, stack_size, start_address,
- parameter, creation_flags, thread_id);
- if (thread)
- return thread;
- }
-
- PSECURITY_DESCRIPTOR sd =
- thread_attributes ? thread_attributes->lpSecurityDescriptor : NULL;
- CLIENT_ID client_id;
-
- NTSTATUS result = g_nt.RtlCreateUserThread(NtCurrentProcess, sd,
- creation_flags & CREATE_SUSPENDED,
- 0, stack_size, 0, start_address,
- parameter, &thread, &client_id);
- if (!NT_SUCCESS(result))
- return 0;
-
- // CSRSS is closed if we got here, so use RtlCreateUserThread from here on.
- use_create_thread = false;
- if (thread_id)
- *thread_id = HandleToUlong(client_id.UniqueThread);
- return thread;
-}
-
-// Cache the default LCID to avoid pinging CSRSS after lockdown.
-// TODO(jschuh): This approach will miss a default locale changes after
-// lockdown. In the future we may want to have the broker check instead.
-LCID WINAPI TargetGetUserDefaultLCID(
- GetUserDefaultLCIDFunction orig_GetUserDefaultLCID) {
- static LCID default_lcid = orig_GetUserDefaultLCID();
- return default_lcid;
-}
-
} // namespace sandbox
diff --git a/sandbox/win/src/process_thread_interception.h b/sandbox/win/src/process_thread_interception.h
index 7d2d533..31dc231 100644
--- a/sandbox/win/src/process_thread_interception.h
+++ b/sandbox/win/src/process_thread_interception.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -83,17 +83,6 @@
LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info,
LPPROCESS_INFORMATION process_information);
-// Interception of CreateThread in kernel32.dll.
-SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateThread(
- CreateThreadFunction orig_CreateThread,
- LPSECURITY_ATTRIBUTES thread_attributes, SIZE_T stack_size,
- LPTHREAD_START_ROUTINE start_address, PVOID parameter,
- DWORD creation_flags, LPDWORD thread_id);
-
-// Interception of GetUserDefaultLCID in kernel32.dll.
-SANDBOX_INTERCEPT LCID WINAPI TargetGetUserDefaultLCID(
- GetUserDefaultLCIDFunction orig_GetUserDefaultLCID);
-
} // extern "C"
} // namespace sandbox
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc
index 64973e9..3960926 100644
--- a/sandbox/win/src/restricted_token.cc
+++ b/sandbox/win/src/restricted_token.cc
@@ -14,7 +14,6 @@
namespace sandbox {
unsigned RestrictedToken::Init(const HANDLE effective_token) {
- DCHECK(!init_);
if (init_)
return ERROR_ALREADY_INITIALIZED;
diff --git a/sandbox/win/src/restricted_token_unittest.cc b/sandbox/win/src/restricted_token_unittest.cc
index 480106e..8186f9c 100644
--- a/sandbox/win/src/restricted_token_unittest.cc
+++ b/sandbox/win/src/restricted_token_unittest.cc
@@ -408,8 +408,8 @@
// elements in the restricting sids list has to be equal.
void CheckRestrictingSid(const ATL::CAccessToken &restricted_token,
ATL::CSid sid, int count) {
- DWORD length = 1000;
- BYTE *memory = new BYTE[1000];
+ DWORD length = 8192;
+ BYTE *memory = new BYTE[length];
TOKEN_GROUPS *groups = reinterpret_cast<TOKEN_GROUPS*>(memory);
ASSERT_TRUE(::GetTokenInformation(restricted_token.GetHandle(),
TokenRestrictedSids,
@@ -530,8 +530,8 @@
ATL::CSid session;
restricted_token.GetLogonSid(&session);
- DWORD length = 1000;
- BYTE *memory = new BYTE[1000];
+ DWORD length = 8192;
+ BYTE *memory = new BYTE[length];
TOKEN_GROUPS *groups = reinterpret_cast<TOKEN_GROUPS*>(memory);
ASSERT_TRUE(::GetTokenInformation(restricted_token.GetHandle(),
TokenRestrictedSids,
@@ -577,9 +577,6 @@
CheckRestrictingSid(restricted_token, user, -1);
}
-// Test to be executed only in release because they are triggering DCHECKs.
-#ifndef _DEBUG
-
// Checks the error code when the object is initialized twice.
TEST(RestrictedTokenTest, DoubleInit) {
RestrictedToken token;
@@ -588,6 +585,4 @@
ASSERT_EQ(ERROR_ALREADY_INITIALIZED, token.Init(NULL));
}
-#endif
-
} // namespace sandbox
diff --git a/sandbox/win/src/restricted_token_utils.cc b/sandbox/win/src/restricted_token_utils.cc
index f3b1859..93b212e 100644
--- a/sandbox/win/src/restricted_token_utils.cc
+++ b/sandbox/win/src/restricted_token_utils.cc
@@ -146,7 +146,7 @@
JobLevel job_level,
HANDLE *const job_handle_ret) {
Job job;
- DWORD err_code = job.Init(job_level, NULL, 0);
+ DWORD err_code = job.Init(job_level, NULL, 0, 0);
if (ERROR_SUCCESS != err_code)
return err_code;
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index 4694fbe..22a2049 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -26,7 +26,8 @@
SUBSYS_PROCESS, // Creation of child processes.
SUBSYS_REGISTRY, // Creation and opening of registry keys.
SUBSYS_SYNC, // Creation of named sync objects.
- SUBSYS_HANDLES // Duplication of handles to other processes.
+ SUBSYS_HANDLES, // Duplication of handles to other processes.
+ SUBSYS_WIN32K_LOCKDOWN // Win32K Lockdown related policy.
};
// Allowable semantics when a rule is matched.
@@ -52,7 +53,10 @@
EVENTS_ALLOW_ANY, // Allows the creation of an event with full access.
EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access.
REG_ALLOW_READONLY, // Allows readonly access to a registry key.
- REG_ALLOW_ANY // Allows read and write access to a registry key.
+ REG_ALLOW_ANY, // Allows read and write access to a registry key.
+ FAKE_USER_GDI_INIT // Fakes user32 and gdi32 initialization. This can
+ // be used to allow the DLLs to load and initialize
+ // even if the process cannot access that subsystem.
};
// Increments the reference count of this object. The reference count must
@@ -128,6 +132,11 @@
// Note: the recommended level is JOB_RESTRICTED or JOB_LOCKDOWN.
virtual ResultCode SetJobLevel(JobLevel job_level, uint32 ui_exceptions) = 0;
+ // Sets a hard limit on the size of the commit set for the sandboxed process.
+ // If the limit is reached, the process will be terminated with
+ // SBOX_FATAL_MEMORY_EXCEEDED (7012).
+ virtual ResultCode SetJobMemoryLimit(size_t memory_limit) = 0;
+
// Specifies the desktop on which the application is going to run. If the
// desktop does not exist, it will be created. If alternate_winstation is
// set to true, the desktop will be created on an alternate window station.
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 3077604..711fafc 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -21,6 +21,8 @@
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_engine_processor.h"
#include "sandbox/win/src/policy_low_level.h"
+#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
+#include "sandbox/win/src/process_mitigations_win32k_policy.h"
#include "sandbox/win/src/process_thread_dispatcher.h"
#include "sandbox/win/src/process_thread_policy.h"
#include "sandbox/win/src/registry_dispatcher.h"
@@ -80,6 +82,7 @@
initial_level_(USER_LOCKDOWN),
job_level_(JOB_LOCKDOWN),
ui_exceptions_(0),
+ memory_limit_(0),
use_alternate_desktop_(false),
use_alternate_winstation_(false),
file_system_init_(false),
@@ -124,6 +127,11 @@
dispatcher = new HandleDispatcher(this);
ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher;
+
+ dispatcher = new ProcessMitigationsWin32KDispatcher(this);
+ ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher;
+ ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher;
+ ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher;
}
PolicyBase::~PolicyBase() {
@@ -170,11 +178,22 @@
}
ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32 ui_exceptions) {
+ if (memory_limit_ && job_level == JOB_NONE) {
+ return SBOX_ERROR_BAD_PARAMS;
+ }
job_level_ = job_level;
ui_exceptions_ = ui_exceptions;
return SBOX_ALL_OK;
}
+ResultCode PolicyBase::SetJobMemoryLimit(size_t memory_limit) {
+ if (memory_limit && job_level_ == JOB_NONE) {
+ return SBOX_ERROR_BAD_PARAMS;
+ }
+ memory_limit_ = memory_limit;
+ return SBOX_ALL_OK;
+}
+
ResultCode PolicyBase::SetAlternateDesktop(bool alternate_winstation) {
use_alternate_desktop_ = true;
use_alternate_winstation_ = alternate_winstation;
@@ -413,6 +432,16 @@
}
break;
}
+
+ case SUBSYS_WIN32K_LOCKDOWN: {
+ if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
+ pattern, semantics,policy_maker_)) {
+ NOTREACHED();
+ return SBOX_ERROR_BAD_PARAMS;
+ }
+ break;
+ }
+
default: {
return SBOX_ERROR_UNSUPPORTED;
}
@@ -471,7 +500,8 @@
if (job_level_ != JOB_NONE) {
// Create the windows job object.
Job job_obj;
- DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_);
+ DWORD result = job_obj.Init(job_level_, NULL, ui_exceptions_,
+ memory_limit_);
if (ERROR_SUCCESS != result) {
return SBOX_ERROR_GENERIC;
}
@@ -667,9 +697,6 @@
}
}
- if (!handle_closer_.SetupHandleInterceptions(&manager))
- return false;
-
if (!SetupBasicInterceptions(&manager))
return false;
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h
index 179cb6c..540f261 100644
--- a/sandbox/win/src/sandbox_policy_base.h
+++ b/sandbox/win/src/sandbox_policy_base.h
@@ -45,6 +45,7 @@
virtual TokenLevel GetLockdownTokenLevel() const OVERRIDE;
virtual ResultCode SetJobLevel(JobLevel job_level,
uint32 ui_exceptions) OVERRIDE;
+ virtual ResultCode SetJobMemoryLimit(size_t memory_limit) OVERRIDE;
virtual ResultCode SetAlternateDesktop(bool alternate_winstation) OVERRIDE;
virtual base::string16 GetAlternateDesktop() const OVERRIDE;
virtual ResultCode CreateAlternateDesktop(bool alternate_winstation) OVERRIDE;
@@ -127,6 +128,7 @@
TokenLevel initial_level_;
JobLevel job_level_;
uint32 ui_exceptions_;
+ size_t memory_limit_;
bool use_alternate_desktop_;
bool use_alternate_winstation_;
// Helps the file system policy initialization.
diff --git a/sandbox/win/src/sandbox_types.h b/sandbox/win/src/sandbox_types.h
index 48f1b61..22840ce 100644
--- a/sandbox/win/src/sandbox_types.h
+++ b/sandbox/win/src/sandbox_types.h
@@ -58,6 +58,7 @@
SBOX_FATAL_CACHEDISABLE = 7009, // Failed to forbid HCKU caching.
SBOX_FATAL_CLOSEHANDLES = 7010, // Failed to close pending handles.
SBOX_FATAL_MITIGATION = 7011, // Could not set the mitigation policy.
+ SBOX_FATAL_MEMORY_EXCEEDED = 7012, // Exceeded the job memory limit.
SBOX_FATAL_LAST
};
diff --git a/sandbox/win/tests/integration_tests/integration_tests.cc b/sandbox/win/tests/integration_tests/integration_tests.cc
index 1996430..bb80931 100644
--- a/sandbox/win/tests/integration_tests/integration_tests.cc
+++ b/sandbox/win/tests/integration_tests/integration_tests.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "sandbox/win/tests/common/controller.h"
@@ -13,6 +16,10 @@
return sandbox::DispatchCall(argc, argv);
}
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
+ TestSuite test_suite(argc, argv);
+ return base::LaunchUnitTests(
+ argc,
+ argv,
+ false,
+ base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
}
diff --git a/sandbox/win/tests/unit_tests/unit_tests.cc b/sandbox/win/tests/unit_tests/unit_tests.cc
index a9623db..df98ba2 100644
--- a/sandbox/win/tests/unit_tests/unit_tests.cc
+++ b/sandbox/win/tests/unit_tests/unit_tests.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
#include "testing/gtest/include/gtest/gtest.h"
int wmain(int argc, wchar_t **argv) {
@@ -11,6 +14,10 @@
return 0;
}
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
+ TestSuite test_suite(argc, argv);
+ return base::LaunchUnitTests(
+ argc,
+ argv,
+ false,
+ base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
}
diff --git a/sandbox/win/tests/validation_tests/commands.cc b/sandbox/win/tests/validation_tests/commands.cc
index e7620c3..4b12094 100644
--- a/sandbox/win/tests/validation_tests/commands.cc
+++ b/sandbox/win/tests/validation_tests/commands.cc
@@ -310,5 +310,24 @@
return SBOX_TEST_SUCCEEDED;
}
+SBOX_TESTS_COMMAND int AllocateCmd(int argc, wchar_t **argv) {
+ if (argc != 1)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ size_t mem_size = static_cast<size_t>(_wtoll(argv[0]));
+ void* memory = ::VirtualAlloc(NULL, mem_size, MEM_COMMIT | MEM_RESERVE,
+ PAGE_READWRITE);
+ if (!memory) {
+ // We need to give the broker a chance to kill our process on failure.
+ ::Sleep(5000);
+ return SBOX_TEST_DENIED;
+ }
+
+ if (!::VirtualFree(memory, 0, MEM_RELEASE))
+ return SBOX_TEST_FAILED;
+
+ return SBOX_TEST_SUCCEEDED;
+}
+
} // namespace sandbox
diff --git a/sandbox/win/tests/validation_tests/suite.cc b/sandbox/win/tests/validation_tests/suite.cc
index f85b8da..4a8ae43 100644
--- a/sandbox/win/tests/validation_tests/suite.cc
+++ b/sandbox/win/tests/validation_tests/suite.cc
@@ -217,4 +217,25 @@
EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
}
+// Tests if an over-limit allocation will be denied.
+TEST(ValidationSuite, TestMemoryLimit) {
+ TestRunner runner;
+ wchar_t command[1024] = {0};
+ const int kAllocationSize = 256 * 1024 * 1024;
+
+ wsprintf(command, L"AllocateCmd %d", kAllocationSize);
+ runner.GetPolicy()->SetJobMemoryLimit(kAllocationSize);
+ EXPECT_EQ(SBOX_FATAL_MEMORY_EXCEEDED, runner.RunTest(command));
+}
+
+// Tests a large allocation will succeed absent limits.
+TEST(ValidationSuite, TestMemoryNoLimit) {
+ TestRunner runner;
+ wchar_t command[1024] = {0};
+ const int kAllocationSize = 256 * 1024 * 1024;
+
+ wsprintf(command, L"AllocateCmd %d", kAllocationSize);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
+}
+
} // namespace sandbox
diff --git a/sandbox/win/tests/validation_tests/unit_tests.cc b/sandbox/win/tests/validation_tests/unit_tests.cc
index 56be2ce..d3fd913 100644
--- a/sandbox/win/tests/validation_tests/unit_tests.cc
+++ b/sandbox/win/tests/validation_tests/unit_tests.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "sandbox/win/tests/common/controller.h"
@@ -11,6 +14,10 @@
return sandbox::DispatchCall(argc, argv);
}
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
+ TestSuite test_suite(argc, argv);
+ return base::LaunchUnitTests(
+ argc,
+ argv,
+ false,
+ base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
}