summaryrefslogtreecommitdiff
path: root/chromium/sandbox
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-03 13:42:47 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:27:51 +0000
commit8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (patch)
treed29d987c4d7b173cf853279b79a51598f104b403 /chromium/sandbox
parent830c9e163d31a9180fadca926b3e1d7dfffb5021 (diff)
downloadqtwebengine-chromium-8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec.tar.gz
BASELINE: Update Chromium to 66.0.3359.156
Change-Id: I0c9831ad39911a086b6377b16f995ad75a51e441 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/sandbox')
-rw-r--r--chromium/sandbox/linux/BUILD.gn10
-rw-r--r--chromium/sandbox/linux/bpf_dsl/dump_bpf.h5
-rw-r--r--chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc1
-rw-r--r--chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc7
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc3
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc5
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc25
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc3
-rw-r--r--chromium/sandbox/linux/services/credentials.cc1
-rw-r--r--chromium/sandbox/linux/services/init_process_reaper.cc7
-rw-r--r--chromium/sandbox/linux/services/init_process_reaper.h10
-rw-r--r--chromium/sandbox/linux/services/libc_interceptor.cc353
-rw-r--r--chromium/sandbox/linux/services/libc_interceptor.h75
-rw-r--r--chromium/sandbox/linux/services/scoped_process_unittest.cc4
-rw-r--r--chromium/sandbox/linux/services/yama_unittests.cc2
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc1
-rw-r--r--chromium/sandbox/mac/seatbelt_exec.cc34
-rw-r--r--chromium/sandbox/mac/seatbelt_exec.h11
-rw-r--r--chromium/sandbox/win/BUILD.gn3
-rw-r--r--chromium/sandbox/win/sandbox_poc/resource.h9
-rw-r--r--chromium/sandbox/win/src/app_container_profile.h87
-rw-r--r--chromium/sandbox/win/src/app_container_profile_base.cc (renamed from chromium/sandbox/win/src/app_container_profile.cc)79
-rw-r--r--chromium/sandbox/win/src/app_container_profile_base.h94
-rw-r--r--chromium/sandbox/win/src/app_container_test.cc16
-rw-r--r--chromium/sandbox/win/src/app_container_unittest.cc69
-rw-r--r--chromium/sandbox/win/src/broker_services.cc8
-rw-r--r--chromium/sandbox/win/src/file_policy_test.cc3
-rw-r--r--chromium/sandbox/win/src/filesystem_interception.h8
-rw-r--r--chromium/sandbox/win/src/handle_closer.cc2
-rw-r--r--chromium/sandbox/win/src/heap_helper.h5
-rw-r--r--chromium/sandbox/win/src/interception.cc6
-rw-r--r--chromium/sandbox/win/src/interceptors_64.h8
-rw-r--r--chromium/sandbox/win/src/job.cc4
-rw-r--r--chromium/sandbox/win/src/named_pipe_interception.h8
-rw-r--r--chromium/sandbox/win/src/policy_low_level.cc1
-rw-r--r--chromium/sandbox/win/src/policy_target.h8
-rw-r--r--chromium/sandbox/win/src/process_mitigations.cc26
-rw-r--r--chromium/sandbox/win/src/process_mitigations.h3
-rw-r--r--chromium/sandbox/win/src/process_thread_interception.h8
-rw-r--r--chromium/sandbox/win/src/registry_interception.h8
-rw-r--r--chromium/sandbox/win/src/resolver.h8
-rw-r--r--chromium/sandbox/win/src/restricted_token_unittest.cc33
-rw-r--r--chromium/sandbox/win/src/restricted_token_utils.cc72
-rw-r--r--chromium/sandbox/win/src/sandbox_policy.h12
-rw-r--r--chromium/sandbox/win/src/sandbox_policy_base.cc42
-rw-r--r--chromium/sandbox/win/src/sandbox_policy_base.h14
-rw-r--r--chromium/sandbox/win/src/sandbox_types.h6
-rw-r--r--chromium/sandbox/win/src/sidestep/mini_disassembler.cpp1
-rw-r--r--chromium/sandbox/win/src/sync_interception.h8
-rw-r--r--chromium/sandbox/win/src/target_interceptions.h8
50 files changed, 944 insertions, 280 deletions
diff --git a/chromium/sandbox/linux/BUILD.gn b/chromium/sandbox/linux/BUILD.gn
index 9d4726f89e4..207ef460ba5 100644
--- a/chromium/sandbox/linux/BUILD.gn
+++ b/chromium/sandbox/linux/BUILD.gn
@@ -37,7 +37,6 @@ group("sandbox") {
public_deps = [
":sandbox_services",
]
-
if (compile_suid_client || is_nacl_nonsfi) {
public_deps += [ ":suid_sandbox_client" ]
}
@@ -150,6 +149,10 @@ source_set("sandbox_linux_unittests_sources") {
"seccomp-bpf/trap_unittest.cc",
]
deps += [ ":bpf_dsl_golden" ]
+
+ if (is_android) {
+ sources += [ "seccomp-bpf-helpers/baseline_policy_android_unittest.cc" ]
+ }
}
if (compile_credentials) {
sources += [
@@ -418,6 +421,11 @@ component("sandbox_services") {
"syscall_broker/broker_process.cc",
"syscall_broker/broker_process.h",
]
+ } else if (!is_android) {
+ sources += [
+ "services/libc_interceptor.cc",
+ "services/libc_interceptor.h",
+ ]
}
}
diff --git a/chromium/sandbox/linux/bpf_dsl/dump_bpf.h b/chromium/sandbox/linux/bpf_dsl/dump_bpf.h
index a7db58981bf..34f1aa99f2b 100644
--- a/chromium/sandbox/linux/bpf_dsl/dump_bpf.h
+++ b/chromium/sandbox/linux/bpf_dsl/dump_bpf.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_LINUX_BPF_DSL_DUMP_BPF_H_
+#define SANDBOX_LINUX_BPF_DSL_DUMP_BPF_H_
+
#include <string>
#include "sandbox/linux/bpf_dsl/codegen.h"
@@ -22,3 +25,5 @@ class SANDBOX_EXPORT DumpBPF {
} // namespace bpf_dsl
} // namespace sandbox
+
+#endif // SANDBOX_LINUX_BPF_DSL_DUMP_BPF_H_
diff --git a/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
index 2fa12b36aaa..a984de1a781 100644
--- a/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
+++ b/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
@@ -774,6 +774,7 @@ ResultExpr SimpleCondTestPolicy::EvaluateSyscall(int sysno) const {
#if defined(__NR_open)
case __NR_open:
flags_argument_position = 1;
+ FALLTHROUGH;
#endif
case __NR_openat: { // open can be a wrapper for openat(2).
if (sysno == __NR_openat)
diff --git a/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
index b1990041425..6840dba8616 100644
--- a/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
+++ b/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
@@ -12,6 +12,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/macros.h"
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
@@ -35,10 +36,6 @@ using bpf_dsl::Allow;
using bpf_dsl::ResultExpr;
using bpf_dsl::Trap;
-bool NoOpCallback() {
- return true;
-}
-
// Test a trap handler that makes use of a broker process to open().
class InitializedOpenBroker {
@@ -52,7 +49,7 @@ class InitializedOpenBroker {
syscall_broker::BrokerFilePermission::ReadOnly("/proc/cpuinfo")};
broker_process_ = std::make_unique<syscall_broker::BrokerProcess>(
EPERM, command_set, permissions);
- BPF_ASSERT(broker_process_->Init(base::Bind(&NoOpCallback)));
+ BPF_ASSERT(broker_process_->Init(base::Bind([]() { return true; })));
initialized_ = true;
}
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 6aab37a88f4..46a54ed1233 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -213,7 +213,8 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
}
#endif
- // crbug.com/701137
+ // On Android, for https://crbug.com/701137.
+ // On Desktop, for https://crbug.com/741984.
if (sysno == __NR_mincore) {
return Allow();
}
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
index 9a37225780b..f0b658d4b63 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
@@ -170,6 +170,11 @@ ResultExpr BaselinePolicyAndroid::EvaluateSyscall(int sysno) const {
return RestrictClockID();
}
+ // https://crbug.com/826289
+ if (sysno == __NR_getrusage) {
+ return RestrictGetrusage();
+ }
+
#if defined(__x86_64__)
if (sysno == __NR_arch_prctl) {
const Arg<int> code(0);
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc
new file mode 100644
index 00000000000..ceecbaf76b0
--- /dev/null
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android_unittest.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 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/linux/seccomp-bpf-helpers/baseline_policy_android.h"
+
+#include <sys/resource.h>
+
+#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+
+namespace sandbox {
+namespace {
+
+BPF_TEST_C(BaselinePolicyAndroid, Getrusage, BaselinePolicyAndroid) {
+ struct rusage usage{};
+
+ errno = 0;
+ BPF_ASSERT_EQ(0, getrusage(RUSAGE_SELF, &usage));
+
+ errno = 0;
+ BPF_ASSERT_EQ(0, getrusage(RUSAGE_THREAD, &usage));
+}
+
+} // namespace
+} // namespace sandbox
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index ada0b8f23ae..2577f02f2e9 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -334,7 +334,8 @@ ResultExpr RestrictPrlimit64(pid_t target_pid) {
ResultExpr RestrictGetrusage() {
const Arg<int> who(0);
- return If(who == RUSAGE_SELF, Allow()).Else(CrashSIGSYS());
+ return If(AnyOf(who == RUSAGE_SELF, who == RUSAGE_THREAD), Allow())
+ .Else(CrashSIGSYS());
}
#endif // !defined(OS_NACL_NONSFI)
diff --git a/chromium/sandbox/linux/services/credentials.cc b/chromium/sandbox/linux/services/credentials.cc
index 65b63adfe2f..ad0714a7f5e 100644
--- a/chromium/sandbox/linux/services/credentials.cc
+++ b/chromium/sandbox/linux/services/credentials.cc
@@ -6,6 +6,7 @@
#include <errno.h>
#include <limits.h>
+#include <sched.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/chromium/sandbox/linux/services/init_process_reaper.cc b/chromium/sandbox/linux/services/init_process_reaper.cc
index 2ff18b5dc28..112fa0a321d 100644
--- a/chromium/sandbox/linux/services/init_process_reaper.cc
+++ b/chromium/sandbox/linux/services/init_process_reaper.cc
@@ -23,7 +23,7 @@ void DoNothingSignalHandler(int signal) {}
} // namespace
-bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback) {
+bool CreateInitProcessReaper(base::OnceClosure post_fork_parent_callback) {
int sync_fds[2];
// We want to use send, so we can't use a pipe
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sync_fds)) {
@@ -54,8 +54,9 @@ bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback) {
DPCHECK(!close_ret);
close_ret = shutdown(sync_fds[1], SHUT_RD);
DPCHECK(!close_ret);
- if (post_fork_parent_callback)
- post_fork_parent_callback->Run();
+ if (!post_fork_parent_callback.is_null())
+ std::move(post_fork_parent_callback).Run();
+
// Tell the child to continue
CHECK(HANDLE_EINTR(send(sync_fds[1], "C", 1, MSG_NOSIGNAL)) == 1);
close_ret = IGNORE_EINTR(close(sync_fds[1]));
diff --git a/chromium/sandbox/linux/services/init_process_reaper.h b/chromium/sandbox/linux/services/init_process_reaper.h
index 840f6fcda7b..a5dbaec79ce 100644
--- a/chromium/sandbox/linux/services/init_process_reaper.h
+++ b/chromium/sandbox/linux/services/init_process_reaper.h
@@ -12,13 +12,11 @@ namespace sandbox {
// The current process will fork(). The parent will become a process reaper
// like init(1). The child will continue normally (after this function
-// returns).
-// If not NULL, |post_fork_parent_callback| will run in the parent almost
-// immediately after fork().
-// Since this function calls fork(), it's very important that the caller has
-// only one thread running.
+// returns). If not empty, |post_fork_parent_callback| will run in the parent
+// almost immediately after fork(). Since this function calls fork(), it's very
+// important that the caller has only one thread running.
SANDBOX_EXPORT bool CreateInitProcessReaper(
- base::Closure* post_fork_parent_callback);
+ base::OnceClosure post_fork_parent_callback);
} // namespace sandbox.
diff --git a/chromium/sandbox/linux/services/libc_interceptor.cc b/chromium/sandbox/linux/services/libc_interceptor.cc
new file mode 100644
index 00000000000..906e1caf8ac
--- /dev/null
+++ b/chromium/sandbox/linux/services/libc_interceptor.cc
@@ -0,0 +1,353 @@
+// Copyright 2018 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/linux/services/libc_interceptor.h"
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <set>
+#include <string>
+
+#include "base/lazy_instance.h"
+#include "base/memory/protected_memory.h"
+#include "base/memory/protected_memory_cfi.h"
+#include "base/pickle.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/posix/global_descriptors.h"
+#include "base/posix/unix_domain_socket.h"
+#include "base/synchronization/lock.h"
+
+namespace sandbox {
+
+namespace {
+
+// The global |g_am_zygote_or_renderer| is true iff we are in a zygote or
+// renderer process. It's set in ZygoteMain and inherited by the renderers when
+// they fork. (This means that it'll be incorrect for global constructor
+// functions and before ZygoteMain is called - beware).
+bool g_am_zygote_or_renderer = false;
+bool g_use_localtime_override = true;
+int g_backchannel_fd = -1;
+
+base::LazyInstance<std::set<std::string>>::Leaky g_timezones =
+ LAZY_INSTANCE_INITIALIZER;
+
+base::LazyInstance<base::Lock>::Leaky g_timezones_lock =
+ LAZY_INSTANCE_INITIALIZER;
+
+bool ReadTimeStruct(base::PickleIterator* iter,
+ struct tm* output,
+ char* timezone_out,
+ size_t timezone_out_len) {
+ int result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_sec = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_min = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_hour = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_mday = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_mon = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_year = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_wday = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_yday = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_isdst = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_gmtoff = result;
+
+ std::string timezone;
+ if (!iter->ReadString(&timezone))
+ return false;
+ if (timezone_out_len) {
+ const size_t copy_len = std::min(timezone_out_len - 1, timezone.size());
+ memcpy(timezone_out, timezone.data(), copy_len);
+ timezone_out[copy_len] = 0;
+ output->tm_zone = timezone_out;
+ } else {
+ base::AutoLock lock(g_timezones_lock.Get());
+ auto ret_pair = g_timezones.Get().insert(timezone);
+ output->tm_zone = ret_pair.first->c_str();
+ }
+
+ return true;
+}
+
+void WriteTimeStruct(base::Pickle* pickle, const struct tm* time) {
+ pickle->WriteInt(time->tm_sec);
+ pickle->WriteInt(time->tm_min);
+ pickle->WriteInt(time->tm_hour);
+ pickle->WriteInt(time->tm_mday);
+ pickle->WriteInt(time->tm_mon);
+ pickle->WriteInt(time->tm_year);
+ pickle->WriteInt(time->tm_wday);
+ pickle->WriteInt(time->tm_yday);
+ pickle->WriteInt(time->tm_isdst);
+ pickle->WriteInt(time->tm_gmtoff);
+ pickle->WriteString(time->tm_zone);
+}
+
+// See
+// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
+void ProxyLocaltimeCallToBrowser(time_t input,
+ struct tm* output,
+ char* timezone_out,
+ size_t timezone_out_len) {
+ base::Pickle request;
+ request.WriteInt(METHOD_LOCALTIME);
+ request.WriteString(
+ std::string(reinterpret_cast<char*>(&input), sizeof(input)));
+
+ memset(output, 0, sizeof(struct tm));
+
+ uint8_t reply_buf[512];
+ const ssize_t r = base::UnixDomainSocket::SendRecvMsg(
+ g_backchannel_fd, reply_buf, sizeof(reply_buf), nullptr, request);
+ if (r == -1)
+ return;
+
+ base::Pickle reply(reinterpret_cast<char*>(reply_buf), r);
+ base::PickleIterator iter(reply);
+ if (!ReadTimeStruct(&iter, output, timezone_out, timezone_out_len)) {
+ memset(output, 0, sizeof(struct tm));
+ }
+}
+
+// The other side of this call is ProxyLocaltimeCallToBrowser().
+bool HandleLocalTime(int fd,
+ base::PickleIterator iter,
+ const std::vector<base::ScopedFD>& fds) {
+ std::string time_string;
+ if (!iter.ReadString(&time_string) || time_string.size() != sizeof(time_t))
+ return false;
+
+ time_t time;
+ memcpy(&time, time_string.data(), sizeof(time));
+ // We use |localtime| here because we need the |tm_zone| field to be filled
+ // out. Since we are a single-threaded process, this is safe.
+ const struct tm* expanded_time = localtime(&time);
+
+ base::Pickle reply;
+ if (expanded_time) {
+ WriteTimeStruct(&reply, expanded_time);
+ } else {
+ // The {} constructor ensures the struct is 0-initialized.
+ struct tm zeroed_time = {};
+ WriteTimeStruct(&reply, &zeroed_time);
+ }
+
+ struct msghdr msg;
+ memset(&msg, 0, sizeof(msg));
+
+ struct iovec iov = {const_cast<void*>(reply.data()), reply.size()};
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (HANDLE_EINTR(sendmsg(fds[0].get(), &msg, MSG_DONTWAIT)) < 0)
+ PLOG(ERROR) << "sendmsg";
+
+ return true;
+}
+
+} // namespace
+
+typedef struct tm* (*LocaltimeFunction)(const time_t* timep);
+typedef struct tm* (*LocaltimeRFunction)(const time_t* timep,
+ struct tm* result);
+struct LibcFunctions {
+ LocaltimeFunction localtime;
+ LocaltimeFunction localtime64;
+ LocaltimeRFunction localtime_r;
+ LocaltimeRFunction localtime64_r;
+};
+
+static pthread_once_t g_libc_funcs_guard = PTHREAD_ONCE_INIT;
+// The libc function pointers are stored in read-only memory after being
+// dynamically resolved as a security mitigation to prevent the pointer from
+// being tampered with. See https://crbug.com/771365 for details.
+static PROTECTED_MEMORY_SECTION base::ProtectedMemory<LibcFunctions>
+ g_libc_funcs;
+
+static void InitLibcLocaltimeFunctions() {
+ auto writer = base::AutoWritableMemory::Create(g_libc_funcs);
+ g_libc_funcs->localtime =
+ reinterpret_cast<LocaltimeFunction>(dlsym(RTLD_NEXT, "localtime"));
+ g_libc_funcs->localtime64 =
+ reinterpret_cast<LocaltimeFunction>(dlsym(RTLD_NEXT, "localtime64"));
+ g_libc_funcs->localtime_r =
+ reinterpret_cast<LocaltimeRFunction>(dlsym(RTLD_NEXT, "localtime_r"));
+ g_libc_funcs->localtime64_r =
+ reinterpret_cast<LocaltimeRFunction>(dlsym(RTLD_NEXT, "localtime64_r"));
+
+ if (!g_libc_funcs->localtime || !g_libc_funcs->localtime_r) {
+ // http://code.google.com/p/chromium/issues/detail?id=16800
+ //
+ // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces
+ // it with a version which doesn't work. In this case we'll get a NULL
+ // result. There's not a lot we can do at this point, so we just bodge it!
+ LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been "
+ "reported to be caused by Nvidia's libGL. You should expect"
+ " time related functions to misbehave. "
+ "http://code.google.com/p/chromium/issues/detail?id=16800";
+ }
+
+ if (!g_libc_funcs->localtime)
+ g_libc_funcs->localtime = gmtime;
+ if (!g_libc_funcs->localtime64)
+ g_libc_funcs->localtime64 = g_libc_funcs->localtime;
+ if (!g_libc_funcs->localtime_r)
+ g_libc_funcs->localtime_r = gmtime_r;
+ if (!g_libc_funcs->localtime64_r)
+ g_libc_funcs->localtime64_r = g_libc_funcs->localtime_r;
+}
+
+// Define localtime_override() function with asm name "localtime", so that all
+// references to localtime() will resolve to this function. Notice that we need
+// to set visibility attribute to "default" to export the symbol, as it is set
+// to "hidden" by default in chrome per build/common.gypi.
+__attribute__((__visibility__("default"))) struct tm* localtime_override(
+ const time_t* timep) __asm__("localtime");
+
+__attribute__((__visibility__("default"))) struct tm* localtime_override(
+ const time_t* timep) {
+ if (g_am_zygote_or_renderer && g_use_localtime_override) {
+ static struct tm time_struct;
+ static char timezone_string[64];
+ ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string,
+ sizeof(timezone_string));
+ return &time_struct;
+ }
+
+ CHECK_EQ(0, pthread_once(&g_libc_funcs_guard, InitLibcLocaltimeFunctions));
+ struct tm* res =
+ base::UnsanitizedCfiCall(g_libc_funcs, &LibcFunctions::localtime)(timep);
+#if defined(MEMORY_SANITIZER)
+ if (res)
+ __msan_unpoison(res, sizeof(*res));
+ if (res->tm_zone)
+ __msan_unpoison_string(res->tm_zone);
+#endif
+ return res;
+}
+
+// Use same trick to override localtime64(), localtime_r() and localtime64_r().
+__attribute__((__visibility__("default"))) struct tm* localtime64_override(
+ const time_t* timep) __asm__("localtime64");
+
+__attribute__((__visibility__("default"))) struct tm* localtime64_override(
+ const time_t* timep) {
+ if (g_am_zygote_or_renderer && g_use_localtime_override) {
+ static struct tm time_struct;
+ static char timezone_string[64];
+ ProxyLocaltimeCallToBrowser(*timep, &time_struct, timezone_string,
+ sizeof(timezone_string));
+ return &time_struct;
+ }
+
+ CHECK_EQ(0, pthread_once(&g_libc_funcs_guard, InitLibcLocaltimeFunctions));
+ struct tm* res = base::UnsanitizedCfiCall(g_libc_funcs,
+ &LibcFunctions::localtime64)(timep);
+#if defined(MEMORY_SANITIZER)
+ if (res)
+ __msan_unpoison(res, sizeof(*res));
+ if (res->tm_zone)
+ __msan_unpoison_string(res->tm_zone);
+#endif
+ return res;
+}
+
+__attribute__((__visibility__("default"))) struct tm* localtime_r_override(
+ const time_t* timep,
+ struct tm* result) __asm__("localtime_r");
+
+__attribute__((__visibility__("default"))) struct tm* localtime_r_override(
+ const time_t* timep,
+ struct tm* result) {
+ if (g_am_zygote_or_renderer && g_use_localtime_override) {
+ ProxyLocaltimeCallToBrowser(*timep, result, nullptr, 0);
+ return result;
+ }
+
+ CHECK_EQ(0, pthread_once(&g_libc_funcs_guard, InitLibcLocaltimeFunctions));
+ struct tm* res = base::UnsanitizedCfiCall(
+ g_libc_funcs, &LibcFunctions::localtime_r)(timep, result);
+#if defined(MEMORY_SANITIZER)
+ if (res)
+ __msan_unpoison(res, sizeof(*res));
+ if (res->tm_zone)
+ __msan_unpoison_string(res->tm_zone);
+#endif
+ return res;
+}
+
+__attribute__((__visibility__("default"))) struct tm* localtime64_r_override(
+ const time_t* timep,
+ struct tm* result) __asm__("localtime64_r");
+
+__attribute__((__visibility__("default"))) struct tm* localtime64_r_override(
+ const time_t* timep,
+ struct tm* result) {
+ if (g_am_zygote_or_renderer && g_use_localtime_override) {
+ ProxyLocaltimeCallToBrowser(*timep, result, nullptr, 0);
+ return result;
+ }
+
+ CHECK_EQ(0, pthread_once(&g_libc_funcs_guard, InitLibcLocaltimeFunctions));
+ struct tm* res = base::UnsanitizedCfiCall(
+ g_libc_funcs, &LibcFunctions::localtime64_r)(timep, result);
+#if defined(MEMORY_SANITIZER)
+ if (res)
+ __msan_unpoison(res, sizeof(*res));
+ if (res->tm_zone)
+ __msan_unpoison_string(res->tm_zone);
+#endif
+ return res;
+}
+
+void SetUseLocaltimeOverride(bool enable) {
+ g_use_localtime_override = enable;
+}
+
+void SetAmZygoteOrRenderer(bool enable, int backchannel_fd) {
+ g_am_zygote_or_renderer = enable;
+ g_backchannel_fd = backchannel_fd;
+}
+
+bool HandleInterceptedCall(int kind,
+ int fd,
+ base::PickleIterator iter,
+ const std::vector<base::ScopedFD>& fds) {
+ if (kind != METHOD_LOCALTIME)
+ return false;
+
+ return HandleLocalTime(fd, iter, fds);
+}
+
+} // namespace sandbox
diff --git a/chromium/sandbox/linux/services/libc_interceptor.h b/chromium/sandbox/linux/services/libc_interceptor.h
new file mode 100644
index 00000000000..c58c9f34604
--- /dev/null
+++ b/chromium/sandbox/linux/services/libc_interceptor.h
@@ -0,0 +1,75 @@
+// Copyright 2018 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_LINUX_SERVICES_LIBC_INTERCEPTOR_H_
+#define SANDBOX_LINUX_SERVICES_LIBC_INTERCEPTOR_H_
+
+#include <vector>
+
+#include "base/files/scoped_file.h"
+#include "base/pickle.h"
+#include "build/build_config.h"
+#include "sandbox/sandbox_export.h"
+
+namespace sandbox {
+
+// Sandbox interception of libc calls.
+//
+// When we are running in a namespace sandbox certain libc calls will fail
+// (localtime being the motivating example - it needs to read /etc/localtime).
+// We need to intercept these calls and proxy them to a parent process.
+// However, these calls may come from us or from our third_party libraries, so
+// in some cases we can't just change the code.
+//
+// It's for these cases that we have the following setup:
+//
+// We define global functions for those functions which we wish to override.
+// Since we will be first in the dynamic resolution order, the dynamic linker
+// will point callers to our versions of these functions. However, we have the
+// same binary for both the browser and the renderers, which means that our
+// overrides will apply in the browser too.
+//
+// Our replacement functions must handle both cases, and either proxy the call
+// to the parent over the IPC back-channel (see
+// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md)
+// or use dlsym with RTLD_NEXT to resolve the symbol, ignoring any symbols in
+// the current module. Use SetUseLocaltimeOverride() and SetAmZygoteOrRenderer()
+// below to control the mode of operation, which defaults using the dlsym
+// approach.
+//
+// Other avenues:
+//
+// Our first attempt involved some assembly to patch the GOT of the current
+// module. This worked, but was platform specific and doesn't catch the case
+// where a library makes a call rather than current module.
+//
+// We also considered patching the function in place, but this would again by
+// platform specific and the above technique seems to work well enough.
+
+// Methods supported over the back-channel to the parent.
+// This isn't the full list, values < 32 are reserved for methods called from
+// Skia, and values >= 64 are reserved for sandbox_ipc_linux.cc.
+enum InterceptedIPCMethods {
+ METHOD_LOCALTIME = 32,
+};
+
+// Currently, only METHOD_LOCALTIME, returns false if |kind| is otherwise.
+SANDBOX_EXPORT bool HandleInterceptedCall(
+ int kind,
+ int fd,
+ base::PickleIterator iter,
+ const std::vector<base::ScopedFD>& fds);
+
+// On Linux, localtime is overridden to use a synchronous IPC to the browser
+// process to determine the locale. This can be disabled, which causes
+// localtime to use UTC instead. https://crbug.com/772503.
+SANDBOX_EXPORT void SetUseLocaltimeOverride(bool enable);
+
+// Turns on/off the libc interception. Called by the zygote and inherited by it
+// children. |backchannel_fd| must be the fd to use for proxying calls.
+SANDBOX_EXPORT void SetAmZygoteOrRenderer(bool enable, int backchannel_fd);
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SERVICES_LIBC_INTERCEPTOR_H_
diff --git a/chromium/sandbox/linux/services/scoped_process_unittest.cc b/chromium/sandbox/linux/services/scoped_process_unittest.cc
index 86f97a8cf43..696e38be598 100644
--- a/chromium/sandbox/linux/services/scoped_process_unittest.cc
+++ b/chromium/sandbox/linux/services/scoped_process_unittest.cc
@@ -63,7 +63,7 @@ TEST(ScopedProcess, DISABLE_ON_ANDROID(ScopedProcessAbort)) {
}
TEST(ScopedProcess, ScopedProcessSignaled) {
- ScopedProcess process(base::Bind(&base::DoNothing));
+ ScopedProcess process{base::DoNothing()};
bool got_signaled = false;
ASSERT_EQ(0, kill(process.GetPid(), SIGKILL));
int exit_code = process.WaitForExit(&got_signaled);
@@ -91,7 +91,7 @@ TEST(ScopedProcess, DiesForReal) {
}
TEST(ScopedProcess, SynchronizationBasic) {
- ScopedProcess process1(base::Bind(&base::DoNothing));
+ ScopedProcess process1{base::DoNothing()};
EXPECT_TRUE(process1.WaitForClosureToRun());
ScopedProcess process2(base::Bind(&DoExit));
diff --git a/chromium/sandbox/linux/services/yama_unittests.cc b/chromium/sandbox/linux/services/yama_unittests.cc
index 0e8355d08e6..aaa2cb07569 100644
--- a/chromium/sandbox/linux/services/yama_unittests.cc
+++ b/chromium/sandbox/linux/services/yama_unittests.cc
@@ -158,7 +158,7 @@ SANDBOX_TEST(Yama, RestrictPtraceIsDefault) {
return;
CHECK(Yama::DisableYamaRestrictions());
- ScopedProcess process1(base::Bind(&base::DoNothing));
+ ScopedProcess process1{base::DoNothing()};
if (Yama::IsEnforcing()) {
// Check that process1 is protected by Yama, even though it has
diff --git a/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc b/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc
index ee4754c0cf1..376dbe7f2ea 100644
--- a/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -20,6 +20,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
diff --git a/chromium/sandbox/mac/seatbelt_exec.cc b/chromium/sandbox/mac/seatbelt_exec.cc
index df8167cf50d..5dc4c9e5e84 100644
--- a/chromium/sandbox/mac/seatbelt_exec.cc
+++ b/chromium/sandbox/mac/seatbelt_exec.cc
@@ -57,10 +57,6 @@ bool ReadOrWrite(int fd,
ssize_t transacted_bytes =
HANDLE_EINTR(Traits::Operate(fd, buffer + offset, bytes_to_transact));
if (transacted_bytes < 0) {
- if (errno == EAGAIN) {
- sched_yield();
- continue;
- }
logging::PError("%s failed", Traits::kNameString);
return false;
}
@@ -76,21 +72,13 @@ bool ReadOrWrite(int fd,
SeatbeltExecClient::SeatbeltExecClient() {
if (pipe(pipe_) != 0)
logging::PFatal("SeatbeltExecClient: pipe failed");
-
- int pipe_flags = fcntl(pipe_[1], F_GETFL);
- if (pipe_flags == -1)
- logging::PFatal("SeatbeltExecClient: fctnl(F_GETFL) failed");
-
- if (fcntl(pipe_[1], F_SETFL, pipe_flags | O_NONBLOCK) == -1)
- logging::PFatal("SeatbeltExecClient: fcntl(F_SETFL) failed");
}
SeatbeltExecClient::~SeatbeltExecClient() {
+ if (pipe_[0] != -1)
+ IGNORE_EINTR(close(pipe_[0]));
if (pipe_[1] != -1)
IGNORE_EINTR(close(pipe_[1]));
- // If pipe() fails, PCHECK() will be hit in the constructor, so this file
- // descriptor should always be closed if the proess is alive at this point.
- IGNORE_EINTR(close(pipe_[0]));
}
bool SeatbeltExecClient::SetBooleanParameter(const std::string& key,
@@ -110,26 +98,30 @@ void SeatbeltExecClient::SetProfile(const std::string& policy) {
policy_.set_profile(policy);
}
-int SeatbeltExecClient::SendProfileAndGetFD() {
+int SeatbeltExecClient::GetReadFD() {
+ return pipe_[0];
+}
+
+bool SeatbeltExecClient::SendProfile() {
+ IGNORE_EINTR(close(pipe_[0]));
+ pipe_[0] = -1;
+
std::string serialized_protobuf;
if (!policy_.SerializeToString(&serialized_protobuf)) {
logging::Error("SeatbeltExecClient: Serializing the profile failed.");
- return -1;
+ return false;
}
if (!WriteString(serialized_protobuf)) {
logging::Error(
"SeatbeltExecClient: Writing the serialized profile failed.");
- return -1;
+ return false;
}
IGNORE_EINTR(close(pipe_[1]));
pipe_[1] = -1;
- if (pipe_[0] < 0)
- logging::Error("SeatbeltExecClient: The pipe returned an invalid fd.");
-
- return pipe_[0];
+ return true;
}
bool SeatbeltExecClient::WriteString(const std::string& str) {
diff --git a/chromium/sandbox/mac/seatbelt_exec.h b/chromium/sandbox/mac/seatbelt_exec.h
index 3366d14e65f..cb12c0c5fb1 100644
--- a/chromium/sandbox/mac/seatbelt_exec.h
+++ b/chromium/sandbox/mac/seatbelt_exec.h
@@ -36,9 +36,14 @@ class SEATBELT_EXPORT SeatbeltExecClient {
// Set the actual sandbox profile, using the scheme-like SBPL.
void SetProfile(const std::string& policy);
- // Sends the policy to the SeatbeltExecServer and returns the communication
- // FD. The FD should be mapped into the sandboxed child process.
- int SendProfileAndGetFD();
+ // This returns the FD used for reading the sandbox profile in the child
+ // process. The FD should be mapped into the sandboxed child process.
+ // This must be called before SendProfile() or the returned FD will be -1.
+ // Callers should check that the returned FD is valid.
+ int GetReadFD();
+
+ // Sends the policy to the SeatbeltExecServer and returns success or failure.
+ bool SendProfile();
// Returns the underlying protobuf for testing purposes.
const mac::SandboxPolicy& GetPolicyForTesting() { return policy_; }
diff --git a/chromium/sandbox/win/BUILD.gn b/chromium/sandbox/win/BUILD.gn
index 01448d4e1e8..4fabf924cd1 100644
--- a/chromium/sandbox/win/BUILD.gn
+++ b/chromium/sandbox/win/BUILD.gn
@@ -12,8 +12,9 @@ static_library("sandbox") {
sources = [
"src/acl.cc",
"src/acl.h",
- "src/app_container_profile.cc",
"src/app_container_profile.h",
+ "src/app_container_profile_base.cc",
+ "src/app_container_profile_base.h",
"src/broker_services.cc",
"src/broker_services.h",
"src/crosscall_client.h",
diff --git a/chromium/sandbox/win/sandbox_poc/resource.h b/chromium/sandbox/win/sandbox_poc/resource.h
index 87ff920ca48..4a2eba6f672 100644
--- a/chromium/sandbox/win/sandbox_poc/resource.h
+++ b/chromium/sandbox/win/sandbox_poc/resource.h
@@ -1,3 +1,10 @@
+// Copyright (c) 2018 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_WIN_SANDBOX_POC_RESOURCE_H_
+#define SANDBOX_WIN_SANDBOX_POC_RESOURCE_H_
+
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by sandbox.rc
@@ -28,3 +35,5 @@
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
+
+#endif // SANDBOX_WIN_SANDBOX_POC_RESOURCE_H_
diff --git a/chromium/sandbox/win/src/app_container_profile.h b/chromium/sandbox/win/src/app_container_profile.h
index 33f79381db8..c95c68e5526 100644
--- a/chromium/sandbox/win/src/app_container_profile.h
+++ b/chromium/sandbox/win/src/app_container_profile.h
@@ -9,13 +9,8 @@
#include <accctrl.h>
-#include <memory>
-#include <vector>
-
#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
#include "base/win/scoped_handle.h"
-#include "sandbox/win/src/security_capabilities.h"
#include "sandbox/win/src/sid.h"
namespace sandbox {
@@ -24,25 +19,24 @@ class AppContainerProfile {
public:
// Increments the reference count of this object. The reference count must
// be incremented if this interface is given to another component.
- void AddRef();
+ virtual void AddRef() = 0;
// Decrements the reference count of this object. When the reference count
// is zero the object is automatically destroyed.
// Indicates that the caller is done with this interface. After calling
// release no other method should be called.
- void Release();
+ virtual void Release() = 0;
// Get a handle to a registry key for this package.
- bool GetRegistryLocation(REGSAM desired_access, base::win::ScopedHandle* key);
+ virtual bool GetRegistryLocation(REGSAM desired_access,
+ base::win::ScopedHandle* key) = 0;
// Get a folder path to a location for this package.
- bool GetFolderPath(base::FilePath* file_path);
+ virtual bool GetFolderPath(base::FilePath* file_path) = 0;
// Get a pipe name usable by this AC.
- bool GetPipePath(const wchar_t* pipe_name, base::FilePath* pipe_path);
-
- // Get the package SID for this AC.
- Sid GetPackageSid() const;
+ virtual bool GetPipePath(const wchar_t* pipe_name,
+ base::FilePath* pipe_path) = 0;
// Do an access check based on this profile for a named object. If method
// returns true then access_status reflects whether access was granted and
@@ -50,70 +44,29 @@ class AppContainerProfile {
// SE_FILE_OBJECT, SE_REGISTRY_KEY, SE_REGISTRY_WOW64_32KEY. See
// ::GetNamedSecurityInfo for more information about how the enumeration is
// used and what format object_name needs to be.
- bool AccessCheck(const wchar_t* object_name,
- SE_OBJECT_TYPE object_type,
- DWORD desired_access,
- DWORD* granted_access,
- BOOL* access_status);
+ virtual bool AccessCheck(const wchar_t* object_name,
+ SE_OBJECT_TYPE object_type,
+ DWORD desired_access,
+ DWORD* granted_access,
+ BOOL* access_status) = 0;
// Adds a capability by name to this profile.
- bool AddCapability(const wchar_t* capability_name);
+ virtual bool AddCapability(const wchar_t* capability_name) = 0;
// Adds a capability from a known list.
- bool AddCapability(WellKnownCapabilities capability);
+ virtual bool AddCapability(WellKnownCapabilities capability) = 0;
// Adds a capability from a SID
- bool AddCapability(const Sid& capability_sid);
+ virtual bool AddCapabilitySddl(const wchar_t* sddl_sid) = 0;
// Adds an impersonation capability by name to this profile.
- bool AddImpersonationCapability(const wchar_t* capability_name);
+ virtual bool AddImpersonationCapability(const wchar_t* capability_name) = 0;
// Adds an impersonation capability from a known list.
- bool AddImpersonationCapability(WellKnownCapabilities capability);
+ virtual bool AddImpersonationCapability(WellKnownCapabilities capability) = 0;
// Adds an impersonation capability from a SID
- bool AddImpersonationCapability(const Sid& capability_sid);
+ virtual bool AddImpersonationCapabilitySddl(const wchar_t* sddl_sid) = 0;
// Enable Low Privilege AC.
- void SetEnableLowPrivilegeAppContainer(bool enable);
- bool GetEnableLowPrivilegeAppContainer();
-
- // Get an allocated SecurityCapabilities object for this App Container.
- std::unique_ptr<SecurityCapabilities> GetSecurityCapabilities();
-
- // Get a vector of capabilities.
- const std::vector<Sid>& GetCapabilities();
-
- // Get a vector of impersonation only capabilities. Used if the process needs
- // a more privileged token to start.
- const std::vector<Sid>& GetImpersonationCapabilities();
-
- // Creates a new AppContainerProfile object. This will create a new profile
- // if it doesn't already exist. The profile must be deleted manually using
- // the Delete method if it's no longer required.
- static scoped_refptr<AppContainerProfile> Create(const wchar_t* package_name,
- const wchar_t* display_name,
- const wchar_t* description);
-
- // Opens an AppContainerProfile object. No checks will be made on
- // whether the package exists or not.
- static scoped_refptr<AppContainerProfile> Open(const wchar_t* package_name);
-
- // Delete a profile based on name. Returns true if successful, or if the
- // package doesn't already exist.
- static bool Delete(const wchar_t* package_name);
-
- private:
- AppContainerProfile(const Sid& package_sid);
- ~AppContainerProfile();
-
- bool BuildLowBoxToken(base::win::ScopedHandle* token);
- bool AddCapability(const Sid& capability_sid, bool impersonation_only);
-
- // Standard object-lifetime reference counter.
- volatile LONG ref_count_;
- Sid package_sid_;
- bool enable_low_privilege_app_container_;
- std::vector<Sid> capabilities_;
- std::vector<Sid> impersonation_capabilities_;
-
- DISALLOW_COPY_AND_ASSIGN(AppContainerProfile);
+ virtual void SetEnableLowPrivilegeAppContainer(bool enable) = 0;
+ virtual bool GetEnableLowPrivilegeAppContainer() = 0;
};
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/app_container_profile.cc b/chromium/sandbox/win/src/app_container_profile_base.cc
index b0cb041e72d..2203b714e75 100644
--- a/chromium/sandbox/win/src/app_container_profile.cc
+++ b/chromium/sandbox/win/src/app_container_profile_base.cc
@@ -10,7 +10,7 @@
#include "base/strings/stringprintf.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_handle.h"
-#include "sandbox/win/src/app_container_profile.h"
+#include "sandbox/win/src/app_container_profile_base.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/win_utils.h"
@@ -79,7 +79,7 @@ class ScopedImpersonation {
} // namespace
// static
-scoped_refptr<AppContainerProfile> AppContainerProfile::Create(
+AppContainerProfileBase* AppContainerProfileBase::Create(
const wchar_t* package_name,
const wchar_t* display_name,
const wchar_t* description) {
@@ -98,11 +98,11 @@ scoped_refptr<AppContainerProfile> AppContainerProfile::Create(
if (FAILED(hr))
return nullptr;
std::unique_ptr<void, FreeSidDeleter> sid_deleter(package_sid);
- return new AppContainerProfile(Sid(package_sid));
+ return new AppContainerProfileBase(Sid(package_sid));
}
// static
-scoped_refptr<AppContainerProfile> AppContainerProfile::Open(
+AppContainerProfileBase* AppContainerProfileBase::Open(
const wchar_t* package_name) {
static auto derive_app_container_sid =
reinterpret_cast<DeriveAppContainerSidFromAppContainerNameFunc*>(
@@ -117,11 +117,11 @@ scoped_refptr<AppContainerProfile> AppContainerProfile::Open(
return nullptr;
std::unique_ptr<void, FreeSidDeleter> sid_deleter(package_sid);
- return new AppContainerProfile(Sid(package_sid));
+ return new AppContainerProfileBase(Sid(package_sid));
}
// static
-bool AppContainerProfile::Delete(const wchar_t* package_name) {
+bool AppContainerProfileBase::Delete(const wchar_t* package_name) {
static auto delete_app_container_profile =
reinterpret_cast<DeleteAppContainerProfileFunc*>(GetProcAddress(
GetModuleHandle(L"userenv"), "DeleteAppContainerProfile"));
@@ -131,26 +131,27 @@ bool AppContainerProfile::Delete(const wchar_t* package_name) {
return SUCCEEDED(delete_app_container_profile(package_name));
}
-AppContainerProfile::AppContainerProfile(const Sid& package_sid)
+AppContainerProfileBase::AppContainerProfileBase(const Sid& package_sid)
: ref_count_(0),
package_sid_(package_sid),
enable_low_privilege_app_container_(false) {}
-AppContainerProfile::~AppContainerProfile() {}
+AppContainerProfileBase::~AppContainerProfileBase() {}
-void AppContainerProfile::AddRef() {
+void AppContainerProfileBase::AddRef() {
::InterlockedIncrement(&ref_count_);
}
-void AppContainerProfile::Release() {
+void AppContainerProfileBase::Release() {
LONG ref_count = ::InterlockedDecrement(&ref_count_);
if (ref_count == 0) {
delete this;
}
}
-bool AppContainerProfile::GetRegistryLocation(REGSAM desired_access,
- base::win::ScopedHandle* key) {
+bool AppContainerProfileBase::GetRegistryLocation(
+ REGSAM desired_access,
+ base::win::ScopedHandle* key) {
static GetAppContainerRegistryLocationFunc*
get_app_container_registry_location =
reinterpret_cast<GetAppContainerRegistryLocationFunc*>(GetProcAddress(
@@ -170,7 +171,7 @@ bool AppContainerProfile::GetRegistryLocation(REGSAM desired_access,
return true;
}
-bool AppContainerProfile::GetFolderPath(base::FilePath* file_path) {
+bool AppContainerProfileBase::GetFolderPath(base::FilePath* file_path) {
static GetAppContainerFolderPathFunc* get_app_container_folder_path =
reinterpret_cast<GetAppContainerFolderPathFunc*>(GetProcAddress(
GetModuleHandle(L"userenv"), "GetAppContainerFolderPath"));
@@ -186,8 +187,8 @@ bool AppContainerProfile::GetFolderPath(base::FilePath* file_path) {
return true;
}
-bool AppContainerProfile::GetPipePath(const wchar_t* pipe_name,
- base::FilePath* pipe_path) {
+bool AppContainerProfileBase::GetPipePath(const wchar_t* pipe_name,
+ base::FilePath* pipe_path) {
base::string16 sddl_str;
if (!package_sid_.ToSddlString(&sddl_str))
return false;
@@ -196,14 +197,15 @@ bool AppContainerProfile::GetPipePath(const wchar_t* pipe_name,
return true;
}
-bool AppContainerProfile::AccessCheck(const wchar_t* object_name,
- SE_OBJECT_TYPE object_type,
- DWORD desired_access,
- DWORD* granted_access,
- BOOL* access_status) {
+bool AppContainerProfileBase::AccessCheck(const wchar_t* object_name,
+ SE_OBJECT_TYPE object_type,
+ DWORD desired_access,
+ DWORD* granted_access,
+ BOOL* access_status) {
GENERIC_MAPPING generic_mapping;
if (!GetGenericMappingForType(object_type, &generic_mapping))
return false;
+ MapGenericMask(&desired_access, &generic_mapping);
PSECURITY_DESCRIPTOR sd = nullptr;
PACL dacl = nullptr;
if (GetNamedSecurityInfo(
@@ -252,20 +254,20 @@ bool AppContainerProfile::AccessCheck(const wchar_t* object_name,
access_status);
}
-bool AppContainerProfile::AddCapability(const wchar_t* capability_name) {
+bool AppContainerProfileBase::AddCapability(const wchar_t* capability_name) {
return AddCapability(Sid::FromNamedCapability(capability_name), false);
}
-bool AppContainerProfile::AddCapability(WellKnownCapabilities capability) {
+bool AppContainerProfileBase::AddCapability(WellKnownCapabilities capability) {
return AddCapability(Sid::FromKnownCapability(capability), false);
}
-bool AppContainerProfile::AddCapability(const Sid& capability_sid) {
- return AddCapability(capability_sid, false);
+bool AppContainerProfileBase::AddCapabilitySddl(const wchar_t* sddl_sid) {
+ return AddCapability(Sid::FromSddlString(sddl_sid), false);
}
-bool AppContainerProfile::AddCapability(const Sid& capability_sid,
- bool impersonation_only) {
+bool AppContainerProfileBase::AddCapability(const Sid& capability_sid,
+ bool impersonation_only) {
if (!capability_sid.IsValid())
return false;
if (!impersonation_only)
@@ -274,48 +276,49 @@ bool AppContainerProfile::AddCapability(const Sid& capability_sid,
return true;
}
-bool AppContainerProfile::AddImpersonationCapability(
+bool AppContainerProfileBase::AddImpersonationCapability(
const wchar_t* capability_name) {
return AddCapability(Sid::FromNamedCapability(capability_name), true);
}
-bool AppContainerProfile::AddImpersonationCapability(
+bool AppContainerProfileBase::AddImpersonationCapability(
WellKnownCapabilities capability) {
return AddCapability(Sid::FromKnownCapability(capability), true);
}
-bool AppContainerProfile::AddImpersonationCapability(
- const Sid& capability_sid) {
- return AddCapability(capability_sid, true);
+bool AppContainerProfileBase::AddImpersonationCapabilitySddl(
+ const wchar_t* sddl_sid) {
+ return AddCapability(Sid::FromSddlString(sddl_sid), true);
}
-const std::vector<Sid>& AppContainerProfile::GetCapabilities() {
+const std::vector<Sid>& AppContainerProfileBase::GetCapabilities() {
return capabilities_;
}
-const std::vector<Sid>& AppContainerProfile::GetImpersonationCapabilities() {
+const std::vector<Sid>&
+AppContainerProfileBase::GetImpersonationCapabilities() {
return impersonation_capabilities_;
}
-Sid AppContainerProfile::GetPackageSid() const {
+Sid AppContainerProfileBase::GetPackageSid() const {
return package_sid_;
}
-void AppContainerProfile::SetEnableLowPrivilegeAppContainer(bool enable) {
+void AppContainerProfileBase::SetEnableLowPrivilegeAppContainer(bool enable) {
enable_low_privilege_app_container_ = enable;
}
-bool AppContainerProfile::GetEnableLowPrivilegeAppContainer() {
+bool AppContainerProfileBase::GetEnableLowPrivilegeAppContainer() {
return enable_low_privilege_app_container_;
}
std::unique_ptr<SecurityCapabilities>
-AppContainerProfile::GetSecurityCapabilities() {
+AppContainerProfileBase::GetSecurityCapabilities() {
return std::unique_ptr<SecurityCapabilities>(
new SecurityCapabilities(package_sid_, capabilities_));
}
-bool AppContainerProfile::BuildLowBoxToken(base::win::ScopedHandle* token) {
+bool AppContainerProfileBase::BuildLowBoxToken(base::win::ScopedHandle* token) {
return CreateLowBoxToken(nullptr, IMPERSONATION,
GetSecurityCapabilities().get(), nullptr, 0,
token) == ERROR_SUCCESS;
diff --git a/chromium/sandbox/win/src/app_container_profile_base.h b/chromium/sandbox/win/src/app_container_profile_base.h
new file mode 100644
index 00000000000..35fb4efdf57
--- /dev/null
+++ b/chromium/sandbox/win/src/app_container_profile_base.h
@@ -0,0 +1,94 @@
+// Copyright 2017 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_APP_CONTAINER_PROFILE_BASE_H_
+#define SANDBOX_SRC_APP_CONTAINER_PROFILE_BASE_H_
+
+#include <windows.h>
+
+#include <accctrl.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/win/scoped_handle.h"
+#include "sandbox/win/src/app_container_profile.h"
+#include "sandbox/win/src/security_capabilities.h"
+#include "sandbox/win/src/sid.h"
+
+namespace sandbox {
+
+class AppContainerProfileBase final : public AppContainerProfile {
+ public:
+ void AddRef() override;
+ void Release() override;
+ bool GetRegistryLocation(REGSAM desired_access,
+ base::win::ScopedHandle* key) override;
+ bool GetFolderPath(base::FilePath* file_path) override;
+ bool GetPipePath(const wchar_t* pipe_name,
+ base::FilePath* pipe_path) override;
+ bool AccessCheck(const wchar_t* object_name,
+ SE_OBJECT_TYPE object_type,
+ DWORD desired_access,
+ DWORD* granted_access,
+ BOOL* access_status) override;
+ bool AddCapability(const wchar_t* capability_name) override;
+ bool AddCapability(WellKnownCapabilities capability) override;
+ bool AddCapabilitySddl(const wchar_t* sddl_sid) override;
+ bool AddImpersonationCapability(const wchar_t* capability_name) override;
+ bool AddImpersonationCapability(WellKnownCapabilities capability) override;
+ bool AddImpersonationCapabilitySddl(const wchar_t* sddl_sid) override;
+ void SetEnableLowPrivilegeAppContainer(bool enable) override;
+ bool GetEnableLowPrivilegeAppContainer() override;
+
+ // Get the package SID for this AC.
+ Sid GetPackageSid() const;
+
+ // Get an allocated SecurityCapabilities object for this App Container.
+ std::unique_ptr<SecurityCapabilities> GetSecurityCapabilities();
+
+ // Get a vector of capabilities.
+ const std::vector<Sid>& GetCapabilities();
+
+ // Get a vector of impersonation only capabilities. Used if the process needs
+ // a more privileged token to start.
+ const std::vector<Sid>& GetImpersonationCapabilities();
+
+ // Creates a new AppContainerProfile object. This will create a new profile
+ // if it doesn't already exist. The profile must be deleted manually using
+ // the Delete method if it's no longer required.
+ static AppContainerProfileBase* Create(const wchar_t* package_name,
+ const wchar_t* display_name,
+ const wchar_t* description);
+
+ // Opens an AppContainerProfile object. No checks will be made on
+ // whether the package exists or not.
+ static AppContainerProfileBase* Open(const wchar_t* package_name);
+
+ // Delete a profile based on name. Returns true if successful, or if the
+ // package doesn't already exist.
+ static bool Delete(const wchar_t* package_name);
+
+ private:
+ AppContainerProfileBase(const Sid& package_sid);
+ ~AppContainerProfileBase();
+
+ bool BuildLowBoxToken(base::win::ScopedHandle* token);
+ bool AddCapability(const Sid& capability_sid, bool impersonation_only);
+
+ // Standard object-lifetime reference counter.
+ volatile LONG ref_count_;
+ Sid package_sid_;
+ bool enable_low_privilege_app_container_;
+ std::vector<Sid> capabilities_;
+ std::vector<Sid> impersonation_capabilities_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppContainerProfileBase);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_APP_CONTAINER_PROFILE_BASE_H_
diff --git a/chromium/sandbox/win/src/app_container_test.cc b/chromium/sandbox/win/src/app_container_test.cc
index 7167354b144..cb725280362 100644
--- a/chromium/sandbox/win/src/app_container_test.cc
+++ b/chromium/sandbox/win/src/app_container_test.cc
@@ -15,7 +15,7 @@
#include "base/win/scoped_handle.h"
#include "base/win/scoped_process_information.h"
#include "base/win/windows_version.h"
-#include "sandbox/win/src/app_container_profile.h"
+#include "sandbox/win/src/app_container_profile_base.h"
#include "sandbox/win/src/sync_policy_test.h"
#include "sandbox/win/src/win_utils.h"
#include "sandbox/win/tests/common/controller.h"
@@ -144,17 +144,19 @@ class AppContainerProfileTest : public ::testing::Test {
return;
package_name_ = GenerateRandomPackageName();
broker_services_ = GetBroker();
- profile_ = AppContainerProfile::Create(package_name_.c_str(), L"Name",
- L"Description");
policy_ = broker_services_->CreatePolicy();
- policy_->SetAppContainerProfile(profile_.get());
+ ASSERT_EQ(SBOX_ALL_OK,
+ policy_->AddAppContainerProfile(package_name_.c_str(), true));
+ // For testing purposes we known the base class so cast directly.
+ profile_ = static_cast<AppContainerProfileBase*>(
+ policy_->GetAppContainerProfile().get());
}
void TearDown() override {
if (scoped_process_info_.IsValid())
::TerminateProcess(scoped_process_info_.process_handle(), 0);
if (profile_)
- AppContainerProfile::Delete(package_name_.c_str());
+ AppContainerProfileBase::Delete(package_name_.c_str());
}
protected:
@@ -175,7 +177,7 @@ class AppContainerProfileTest : public ::testing::Test {
std::wstring package_name_;
BrokerServices* broker_services_;
- scoped_refptr<AppContainerProfile> profile_;
+ scoped_refptr<AppContainerProfileBase> profile_;
scoped_refptr<TargetPolicy> policy_;
base::win::ScopedProcessInformation scoped_process_info_;
};
@@ -210,6 +212,8 @@ TEST_F(AppContainerProfileTest, CheckIncompatibleOptions) {
EXPECT_EQ(SBOX_ERROR_BAD_PARAMS,
policy_->SetIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED));
EXPECT_EQ(SBOX_ERROR_BAD_PARAMS, policy_->SetLowBox(kAppContainerSid));
+ EXPECT_EQ(SBOX_ERROR_BAD_PARAMS,
+ policy_->SetProcessMitigations(MITIGATION_HEAP_TERMINATE));
}
TEST_F(AppContainerProfileTest, NoCapabilities) {
diff --git a/chromium/sandbox/win/src/app_container_unittest.cc b/chromium/sandbox/win/src/app_container_unittest.cc
index b61541f8aac..f3e70c35f41 100644
--- a/chromium/sandbox/win/src/app_container_unittest.cc
+++ b/chromium/sandbox/win/src/app_container_unittest.cc
@@ -17,7 +17,7 @@
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/win/windows_version.h"
-#include "sandbox/win/src/app_container_profile.h"
+#include "sandbox/win/src/app_container_profile_base.h"
#include "sandbox/win/src/security_capabilities.h"
#include "sandbox/win/src/sid.h"
#include "sandbox/win/src/win_utils.h"
@@ -143,7 +143,7 @@ void AccessCheckFile(AppContainerProfile* profile,
DWORD granted_access;
BOOL access_status;
ASSERT_TRUE(profile->AccessCheck(path.value().c_str(), SE_FILE_OBJECT,
- FILE_READ_DATA, &granted_access,
+ desired_access, &granted_access,
&access_status));
ASSERT_EQ(expected_status, access_status);
if (access_status)
@@ -181,11 +181,12 @@ TEST(AppContainerTest, CreateAndDeleteAppContainerProfile) {
std::wstring package_name = GenerateRandomPackageName();
EXPECT_FALSE(ProfileExist(package_name));
- scoped_refptr<AppContainerProfile> profile = AppContainerProfile::Create(
- package_name.c_str(), L"Name", L"Description");
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Create(package_name.c_str(), L"Name",
+ L"Description");
ASSERT_NE(nullptr, profile.get());
EXPECT_TRUE(ProfileExist(package_name));
- EXPECT_TRUE(AppContainerProfile::Delete(package_name.c_str()));
+ EXPECT_TRUE(AppContainerProfileBase::Delete(package_name.c_str()));
EXPECT_FALSE(ProfileExist(package_name));
}
@@ -195,19 +196,20 @@ TEST(AppContainerTest, CreateAndOpenAppContainerProfile) {
std::wstring package_name = GenerateRandomPackageName();
EXPECT_FALSE(ProfileExist(package_name));
- scoped_refptr<AppContainerProfile> profile = AppContainerProfile::Create(
- package_name.c_str(), L"Name", L"Description");
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Create(package_name.c_str(), L"Name",
+ L"Description");
ASSERT_NE(nullptr, profile.get());
EXPECT_TRUE(ProfileExist(package_name));
- scoped_refptr<AppContainerProfile> open_profile =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> open_profile =
+ AppContainerProfileBase::Open(package_name.c_str());
ASSERT_NE(nullptr, profile.get());
EXPECT_TRUE(::EqualSid(profile->GetPackageSid().GetPSID(),
open_profile->GetPackageSid().GetPSID()));
- EXPECT_TRUE(AppContainerProfile::Delete(package_name.c_str()));
+ EXPECT_TRUE(AppContainerProfileBase::Delete(package_name.c_str()));
EXPECT_FALSE(ProfileExist(package_name));
- scoped_refptr<AppContainerProfile> open_profile2 =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> open_profile2 =
+ AppContainerProfileBase::Open(package_name.c_str());
EXPECT_FALSE(ProfileExist(package_name));
}
@@ -216,8 +218,8 @@ TEST(AppContainerTest, SetLowPrivilegeAppContainer) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_RS1)
return;
std::wstring package_name = GenerateRandomPackageName();
- scoped_refptr<AppContainerProfile> profile =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Open(package_name.c_str());
ASSERT_NE(nullptr, profile.get());
profile->SetEnableLowPrivilegeAppContainer(true);
EXPECT_TRUE(profile->GetEnableLowPrivilegeAppContainer());
@@ -228,8 +230,8 @@ TEST(AppContainerTest, OpenAppContainerProfileAndGetSecurityCapabilities) {
return;
std::wstring package_name = GenerateRandomPackageName();
- scoped_refptr<AppContainerProfile> profile =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Open(package_name.c_str());
ASSERT_NE(nullptr, profile.get());
std::vector<Sid> capabilities;
@@ -245,9 +247,9 @@ TEST(AppContainerTest, OpenAppContainerProfileAndGetSecurityCapabilities) {
ASSERT_TRUE(profile->AddCapability(kInternetClient));
capabilities.push_back(Sid::FromKnownCapability(kInternetClient));
- Sid sid_sddl = Sid::FromSddlString(L"S-1-15-3-1");
- ASSERT_TRUE(profile->AddCapability(sid_sddl));
- capabilities.push_back(sid_sddl);
+ const wchar_t kSddlSid[] = L"S-1-15-3-1";
+ ASSERT_TRUE(profile->AddCapabilitySddl(kSddlSid));
+ capabilities.push_back(Sid::FromSddlString(kSddlSid));
auto with_capabilities = profile->GetSecurityCapabilities();
ASSERT_TRUE(ValidSecurityCapabilities(
with_capabilities.get(), profile->GetPackageSid(), capabilities));
@@ -258,8 +260,9 @@ TEST(AppContainerTest, GetResources) {
return;
std::wstring package_name = GenerateRandomPackageName();
- scoped_refptr<AppContainerProfile> profile = AppContainerProfile::Create(
- package_name.c_str(), L"Name", L"Description");
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Create(package_name.c_str(), L"Name",
+ L"Description");
ASSERT_NE(nullptr, profile.get());
base::win::ScopedHandle key;
EXPECT_TRUE(profile->GetRegistryLocation(KEY_READ, &key));
@@ -275,7 +278,7 @@ TEST(AppContainerTest, GetResources) {
pipe_path.value().c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE,
PIPE_UNLIMITED_INSTANCES, 0, 0, 0, nullptr));
EXPECT_TRUE(pipe_handle.IsValid());
- EXPECT_TRUE(AppContainerProfile::Delete(package_name.c_str()));
+ EXPECT_TRUE(AppContainerProfileBase::Delete(package_name.c_str()));
}
TEST(AppContainerTest, AccessCheckFile) {
@@ -284,8 +287,8 @@ TEST(AppContainerTest, AccessCheckFile) {
// We don't need a valid profile to do the access check tests.
std::wstring package_name = GenerateRandomPackageName();
- scoped_refptr<AppContainerProfile> profile =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Open(package_name.c_str());
profile->AddCapability(kInternetClient);
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
@@ -300,6 +303,10 @@ TEST(AppContainerTest, AccessCheckFile) {
Sid::FromKnownCapability(kInternetClient), FILE_READ_DATA,
FILE_READ_DATA, TRUE);
+ // Check mapping generic access rights.
+ AccessCheckFile(profile.get(), path, ::WinBuiltinAnyPackageSid,
+ GENERIC_READ | GENERIC_EXECUTE,
+ FILE_GENERIC_READ | FILE_GENERIC_EXECUTE, TRUE);
// No support for LPAC less than Win10 RS1.
if (base::win::GetVersion() < base::win::VERSION_WIN10_RS1)
return;
@@ -316,8 +323,8 @@ TEST(AppContainerTest, AccessCheckRegistry) {
// We don't need a valid profile to do the access check tests.
std::wstring package_name = GenerateRandomPackageName();
- scoped_refptr<AppContainerProfile> profile =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Open(package_name.c_str());
// Ensure the key doesn't exist.
RegDeleteKey(HKEY_CURRENT_USER, package_name.c_str());
SECURITY_ATTRIBUTES_SDDL sa(
@@ -346,8 +353,8 @@ TEST(AppContainerTest, ImpersonationCapabilities) {
return;
std::wstring package_name = GenerateRandomPackageName();
- scoped_refptr<AppContainerProfile> profile =
- AppContainerProfile::Open(package_name.c_str());
+ scoped_refptr<AppContainerProfileBase> profile =
+ AppContainerProfileBase::Open(package_name.c_str());
ASSERT_NE(nullptr, profile.get());
std::vector<Sid> capabilities;
@@ -371,9 +378,9 @@ TEST(AppContainerTest, ImpersonationCapabilities) {
impersonation_capabilities.push_back(
Sid::FromNamedCapability(L"FakeCapability"));
}
- Sid sid_sddl = Sid::FromSddlString(L"S-1-15-3-1");
- ASSERT_TRUE(profile->AddImpersonationCapability(sid_sddl));
- impersonation_capabilities.push_back(sid_sddl);
+ const wchar_t kSddlSid[] = L"S-1-15-3-1";
+ ASSERT_TRUE(profile->AddImpersonationCapabilitySddl(kSddlSid));
+ impersonation_capabilities.push_back(Sid::FromSddlString(kSddlSid));
ASSERT_TRUE(CompareSidVectors(profile->GetCapabilities(), capabilities));
ASSERT_TRUE(CompareSidVectors(profile->GetImpersonationCapabilities(),
impersonation_capabilities));
diff --git a/chromium/sandbox/win/src/broker_services.cc b/chromium/sandbox/win/src/broker_services.cc
index ab899956a88..c9415c2b388 100644
--- a/chromium/sandbox/win/src/broker_services.cc
+++ b/chromium/sandbox/win/src/broker_services.cc
@@ -368,8 +368,8 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
if (inherited_handle_list.size())
++attribute_count;
- scoped_refptr<AppContainerProfile> profile =
- policy_base->GetAppContainerProfile();
+ scoped_refptr<AppContainerProfileBase> profile =
+ policy_base->GetAppContainerProfileBase();
if (profile) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return SBOX_ERROR_BAD_PARAMS;
@@ -441,7 +441,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
// Construct the thread pool here in case it is expensive.
// The thread pool is shared by all the targets
if (!thread_pool_)
- thread_pool_ = base::MakeUnique<Win2kThreadPool>();
+ thread_pool_ = std::make_unique<Win2kThreadPool>();
// Create the TargetProcess object and spawn the target suspended. Note that
// Brokerservices does not own the target object. It is owned by the Policy.
@@ -481,7 +481,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
// the job object generates notifications using the completion port.
if (job.IsValid()) {
std::unique_ptr<JobTracker> tracker =
- base::MakeUnique<JobTracker>(std::move(job), policy_base);
+ std::make_unique<JobTracker>(std::move(job), policy_base);
// There is no obvious recovery after failure here. Previous version with
// SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
diff --git a/chromium/sandbox/win/src/file_policy_test.cc b/chromium/sandbox/win/src/file_policy_test.cc
index 59d6532aa36..3eb1bb64513 100644
--- a/chromium/sandbox/win/src/file_policy_test.cc
+++ b/chromium/sandbox/win/src/file_policy_test.cc
@@ -291,7 +291,8 @@ TEST(FilePolicyTest, AllowNtCreateWithNativePath) {
::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
- std::transform(nt_path.begin(), nt_path.end(), nt_path.begin(), std::tolower);
+ for (wchar_t& c : nt_path)
+ c = std::tolower(c);
::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
}
diff --git a/chromium/sandbox/win/src/filesystem_interception.h b/chromium/sandbox/win/src/filesystem_interception.h
index d5d83318b1c..d9d92f7fa4f 100644
--- a/chromium/sandbox/win/src/filesystem_interception.h
+++ b/chromium/sandbox/win/src/filesystem_interception.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_FILESYSTEM_INTERCEPTION_H_
+#define SANDBOX_WIN_SRC_FILESYSTEM_INTERCEPTION_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_FILESYSTEM_INTERCEPTION_H__
-#define SANDBOX_SRC_FILESYSTEM_INTERCEPTION_H__
-
namespace sandbox {
extern "C" {
@@ -64,4 +64,4 @@ TargetNtSetInformationFile(NtSetInformationFileFunction orig_SetInformationFile,
} // namespace sandbox
-#endif // SANDBOX_SRC_FILESYSTEM_INTERCEPTION_H__
+#endif // SANDBOX_WIN_SRC_FILESYSTEM_INTERCEPTION_H_
diff --git a/chromium/sandbox/win/src/handle_closer.cc b/chromium/sandbox/win/src/handle_closer.cc
index 72e64bc0379..3e2f1f00932 100644
--- a/chromium/sandbox/win/src/handle_closer.cc
+++ b/chromium/sandbox/win/src/handle_closer.cc
@@ -147,7 +147,7 @@ bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) {
output = &list_entry->handle_type[0];
// Copy the typename and set the offset and count.
- i->first._Copy_s(output, i->first.size(), i->first.size());
+ i->first.copy(output, i->first.size());
*(output += i->first.size()) = L'\0';
output++;
list_entry->offset_to_names =
diff --git a/chromium/sandbox/win/src/heap_helper.h b/chromium/sandbox/win/src/heap_helper.h
index 63ce34570cd..302a3c4e29d 100644
--- a/chromium/sandbox/win/src/heap_helper.h
+++ b/chromium/sandbox/win/src/heap_helper.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_HEAP_HELPER_H_
+#define SANDBOX_WIN_SRC_HEAP_HELPER_H_
+
#include <windows.h>
#include "base/win/windows_version.h"
@@ -19,3 +22,5 @@ bool HeapFlags(HANDLE handle, DWORD* flags);
HANDLE FindCsrPortHeap();
} // namespace sandbox
+
+#endif // SANDBOX_WIN_SRC_HEAP_HELPER_H_
diff --git a/chromium/sandbox/win/src/interception.cc b/chromium/sandbox/win/src/interception.cc
index 600f7b19cc4..47a8a65dc7d 100644
--- a/chromium/sandbox/win/src/interception.cc
+++ b/chromium/sandbox/win/src/interception.cc
@@ -276,7 +276,7 @@ bool InterceptionManager::SetupDllInfo(const InterceptionData& data,
dll_info->record_bytes = required;
dll_info->offset_to_functions = required;
dll_info->num_functions = 0;
- data.dll._Copy_s(dll_info->dll_name, data.dll.size(), data.dll.size());
+ data.dll.copy(dll_info->dll_name, data.dll.size());
dll_info->dll_name[data.dll.size()] = L'\0';
return true;
@@ -317,12 +317,12 @@ bool InterceptionManager::SetupInterceptionInfo(const InterceptionData& data,
function->interceptor_address = data.interceptor_address;
char* names = function->function;
- data.function._Copy_s(names, name_bytes, name_bytes);
+ data.function.copy(names, name_bytes);
names += name_bytes;
*names++ = '\0';
// interceptor follows the function_name
- data.interceptor._Copy_s(names, interceptor_bytes, interceptor_bytes);
+ data.interceptor.copy(names, interceptor_bytes);
names += interceptor_bytes;
*names++ = '\0';
diff --git a/chromium/sandbox/win/src/interceptors_64.h b/chromium/sandbox/win/src/interceptors_64.h
index d1b2e5776d4..1016b7cfd64 100644
--- a/chromium/sandbox/win/src/interceptors_64.h
+++ b/chromium/sandbox/win/src/interceptors_64.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_INTERCEPTORS_64_H_
+#define SANDBOX_WIN_SRC_INTERCEPTORS_64_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_INTERCEPTORS_64_H_
-#define SANDBOX_SRC_INTERCEPTORS_64_H_
-
namespace sandbox {
extern "C" {
@@ -314,4 +314,4 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetConfigureOPMProtectedOutput64(
} // namespace sandbox
-#endif // SANDBOX_SRC_INTERCEPTORS_64_H_
+#endif // SANDBOX_WIN_SRC_INTERCEPTORS_64_H_
diff --git a/chromium/sandbox/win/src/job.cc b/chromium/sandbox/win/src/job.cc
index 831825cd486..cb1c6b9f475 100644
--- a/chromium/sandbox/win/src/job.cc
+++ b/chromium/sandbox/win/src/job.cc
@@ -37,22 +37,26 @@ DWORD Job::Init(JobLevel security_level,
case JOB_LOCKDOWN: {
jeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
+ FALLTHROUGH;
}
case JOB_RESTRICTED: {
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS;
+ FALLTHROUGH;
}
case JOB_LIMITED_USER: {
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
jeli.BasicLimitInformation.ActiveProcessLimit = 1;
+ FALLTHROUGH;
}
case JOB_INTERACTIVE: {
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
+ FALLTHROUGH;
}
case JOB_UNPROTECTED: {
if (memory_limit) {
diff --git a/chromium/sandbox/win/src/named_pipe_interception.h b/chromium/sandbox/win/src/named_pipe_interception.h
index 276b4cf0b90..8eedd14b31a 100644
--- a/chromium/sandbox/win/src/named_pipe_interception.h
+++ b/chromium/sandbox/win/src/named_pipe_interception.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_NAMED_PIPE_INTERCEPTION_H_
+#define SANDBOX_WIN_SRC_NAMED_PIPE_INTERCEPTION_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_NAMED_PIPE_INTERCEPTION_H__
-#define SANDBOX_SRC_NAMED_PIPE_INTERCEPTION_H__
-
namespace sandbox {
extern "C" {
@@ -38,4 +38,4 @@ TargetCreateNamedPipeW(CreateNamedPipeWFunction orig_CreateNamedPipeW,
} // namespace sandbox
-#endif // SANDBOX_SRC_NAMED_PIPE_INTERCEPTION_H__
+#endif // SANDBOX_WIN_SRC_NAMED_PIPE_INTERCEPTION_H_
diff --git a/chromium/sandbox/win/src/policy_low_level.cc b/chromium/sandbox/win/src/policy_low_level.cc
index 86e2a13dcad..d2c9a6f8564 100644
--- a/chromium/sandbox/win/src/policy_low_level.cc
+++ b/chromium/sandbox/win/src/policy_low_level.cc
@@ -265,6 +265,7 @@ bool PolicyRule::AddStringMatch(RuleType rule_type,
if (L'?' == current_char[1]) {
++current_char;
}
+ FALLTHROUGH;
default:
fragment += *current_char;
last_char = kLastCharIsAlpha;
diff --git a/chromium/sandbox/win/src/policy_target.h b/chromium/sandbox/win/src/policy_target.h
index 8a2b437095e..373714e197c 100644
--- a/chromium/sandbox/win/src/policy_target.h
+++ b/chromium/sandbox/win/src/policy_target.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_POLICY_TARGET_H_
+#define SANDBOX_WIN_SRC_POLICY_TARGET_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_POLICY_TARGET_H__
-#define SANDBOX_SRC_POLICY_TARGET_H__
-
namespace sandbox {
struct CountedParameterSetBase;
@@ -42,4 +42,4 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadTokenEx(
} // namespace sandbox
-#endif // SANDBOX_SRC_POLICY_TARGET_H__
+#endif // SANDBOX_WIN_SRC_POLICY_TARGET_H_
diff --git a/chromium/sandbox/win/src/process_mitigations.cc b/chromium/sandbox/win/src/process_mitigations.cc
index c6c2d38144b..54c756aece4 100644
--- a/chromium/sandbox/win/src/process_mitigations.cc
+++ b/chromium/sandbox/win/src/process_mitigations.cc
@@ -431,20 +431,22 @@ bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process,
return true;
}
+MitigationFlags GetAllowedPostStartupProcessMitigations() {
+ return MITIGATION_HEAP_TERMINATE | MITIGATION_DEP |
+ MITIGATION_DEP_NO_ATL_THUNK | MITIGATION_RELOCATE_IMAGE |
+ MITIGATION_RELOCATE_IMAGE_REQUIRED | MITIGATION_BOTTOM_UP_ASLR |
+ MITIGATION_STRICT_HANDLE_CHECKS | MITIGATION_EXTENSION_POINT_DISABLE |
+ MITIGATION_DLL_SEARCH_ORDER | MITIGATION_HARDEN_TOKEN_IL_POLICY |
+ MITIGATION_WIN32K_DISABLE | MITIGATION_DYNAMIC_CODE_DISABLE |
+ MITIGATION_DYNAMIC_CODE_DISABLE_WITH_OPT_OUT |
+ MITIGATION_FORCE_MS_SIGNED_BINS | MITIGATION_NONSYSTEM_FONT_DISABLE |
+ MITIGATION_IMAGE_LOAD_NO_REMOTE | MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
+ MITIGATION_IMAGE_LOAD_PREFER_SYS32;
+}
+
bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) {
// All of these mitigations can be enabled after startup.
- return !(
- flags &
- ~(MITIGATION_HEAP_TERMINATE | MITIGATION_DEP |
- MITIGATION_DEP_NO_ATL_THUNK | MITIGATION_RELOCATE_IMAGE |
- MITIGATION_RELOCATE_IMAGE_REQUIRED | MITIGATION_BOTTOM_UP_ASLR |
- MITIGATION_STRICT_HANDLE_CHECKS | MITIGATION_EXTENSION_POINT_DISABLE |
- MITIGATION_DLL_SEARCH_ORDER | MITIGATION_HARDEN_TOKEN_IL_POLICY |
- MITIGATION_WIN32K_DISABLE | MITIGATION_DYNAMIC_CODE_DISABLE |
- MITIGATION_DYNAMIC_CODE_DISABLE_WITH_OPT_OUT |
- MITIGATION_FORCE_MS_SIGNED_BINS | MITIGATION_NONSYSTEM_FONT_DISABLE |
- MITIGATION_IMAGE_LOAD_NO_REMOTE | MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
- MITIGATION_IMAGE_LOAD_PREFER_SYS32));
+ return !(flags & ~GetAllowedPostStartupProcessMitigations());
}
bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) {
diff --git a/chromium/sandbox/win/src/process_mitigations.h b/chromium/sandbox/win/src/process_mitigations.h
index 5d9b667ec84..cf1844a471a 100644
--- a/chromium/sandbox/win/src/process_mitigations.h
+++ b/chromium/sandbox/win/src/process_mitigations.h
@@ -38,6 +38,9 @@ void ConvertProcessMitigationsToPolicy(MitigationFlags flags,
bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process,
MitigationFlags flags);
+// Returns the list of process mitigations which can be enabled post startup.
+MitigationFlags GetAllowedPostStartupProcessMitigations();
+
// Returns true if all the supplied flags can be set after a process starts.
bool CanSetProcessMitigationsPostStartup(MitigationFlags flags);
diff --git a/chromium/sandbox/win/src/process_thread_interception.h b/chromium/sandbox/win/src/process_thread_interception.h
index c4b483cb801..2608d7d31ea 100644
--- a/chromium/sandbox/win/src/process_thread_interception.h
+++ b/chromium/sandbox/win/src/process_thread_interception.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_PROCESS_THREAD_INTERCEPTION_H_
+#define SANDBOX_WIN_SRC_PROCESS_THREAD_INTERCEPTION_H_
+
#include <windows.h>
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_PROCESS_THREAD_INTERCEPTION_H__
-#define SANDBOX_SRC_PROCESS_THREAD_INTERCEPTION_H__
-
namespace sandbox {
namespace {
@@ -98,4 +98,4 @@ TargetCreateThread(CreateThreadFunction orig_CreateThread,
} // namespace sandbox
-#endif // SANDBOX_SRC_PROCESS_THREAD_INTERCEPTION_H__
+#endif // SANDBOX_WIN_SRC_PROCESS_THREAD_INTERCEPTION_H_
diff --git a/chromium/sandbox/win/src/registry_interception.h b/chromium/sandbox/win/src/registry_interception.h
index c3cbde02e72..f47e56ce39c 100644
--- a/chromium/sandbox/win/src/registry_interception.h
+++ b/chromium/sandbox/win/src/registry_interception.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_REGISTRY_INTERCEPTION_H_
+#define SANDBOX_WIN_SRC_REGISTRY_INTERCEPTION_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_REGISTRY_INTERCEPTION_H__
-#define SANDBOX_SRC_REGISTRY_INTERCEPTION_H__
-
namespace sandbox {
extern "C" {
@@ -35,4 +35,4 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenKeyEx(
} // namespace sandbox
-#endif // SANDBOX_SRC_REGISTRY_INTERCEPTION_H__
+#endif // SANDBOX_WIN_SRC_REGISTRY_INTERCEPTION_H_
diff --git a/chromium/sandbox/win/src/resolver.h b/chromium/sandbox/win/src/resolver.h
index 3091d2f94e6..3ce427b74b9 100644
--- a/chromium/sandbox/win/src/resolver.h
+++ b/chromium/sandbox/win/src/resolver.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_RESOLVER_H_
+#define SANDBOX_WIN_SRC_RESOLVER_H_
+
// Defines ResolverThunk, the interface for classes that perform interceptions.
// For more details see
// http://dev.chromium.org/developers/design-documents/sandbox .
@@ -11,9 +14,6 @@
#include "base/macros.h"
#include "sandbox/win/src/nt_internals.h"
-#ifndef SANDBOX_SRC_RESOLVER_H__
-#define SANDBOX_SRC_RESOLVER_H__
-
namespace sandbox {
// A resolver is the object in charge of performing the actual interception of
@@ -104,4 +104,4 @@ class ResolverThunk {
} // namespace sandbox
-#endif // SANDBOX_SRC_RESOLVER_H__
+#endif // SANDBOX_WIN_SRC_RESOLVER_H_
diff --git a/chromium/sandbox/win/src/restricted_token_unittest.cc b/chromium/sandbox/win/src/restricted_token_unittest.cc
index fad38cc8c20..6c674d54993 100644
--- a/chromium/sandbox/win/src/restricted_token_unittest.cc
+++ b/chromium/sandbox/win/src/restricted_token_unittest.cc
@@ -128,6 +128,39 @@ void CheckLowBoxToken(const base::win::ScopedHandle& token,
EXPECT_TRUE(::EqualSid(capabilities->Groups[index].Sid,
security_capabilities->Capabilities[index].Sid));
}
+
+ DWORD length_needed = 0;
+ ::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION, nullptr, 0,
+ &length_needed);
+ ASSERT_EQ(::GetLastError(), DWORD{ERROR_INSUFFICIENT_BUFFER});
+
+ std::vector<char> security_desc_buffer(length_needed);
+ SECURITY_DESCRIPTOR* security_desc =
+ reinterpret_cast<SECURITY_DESCRIPTOR*>(security_desc_buffer.data());
+
+ ASSERT_TRUE(::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION,
+ security_desc, length_needed,
+ &length_needed));
+
+ ATL::CSecurityDesc token_sd(*security_desc);
+ ATL::CSid check_sid(
+ static_cast<SID*>(security_capabilities->AppContainerSid));
+ bool package_sid_found = false;
+
+ ATL::CDacl dacl;
+ ASSERT_TRUE(token_sd.GetDacl(&dacl));
+ unsigned int ace_count = dacl.GetAceCount();
+ for (unsigned int i = 0; i < ace_count; ++i) {
+ ATL::CSid sid;
+ ACCESS_MASK mask = 0;
+ BYTE type = 0;
+ dacl.GetAclEntry(i, &sid, &mask, &type);
+ if (sid == check_sid && mask == TOKEN_ALL_ACCESS &&
+ type == ACCESS_ALLOWED_ACE_TYPE) {
+ package_sid_found = true;
+ }
+ }
+ ASSERT_TRUE(package_sid_found);
}
// Checks if a sid is in the restricting list of the restricted token.
diff --git a/chromium/sandbox/win/src/restricted_token_utils.cc b/chromium/sandbox/win/src/restricted_token_utils.cc
index 104ae07caab..2653090910c 100644
--- a/chromium/sandbox/win/src/restricted_token_utils.cc
+++ b/chromium/sandbox/win/src/restricted_token_utils.cc
@@ -23,6 +23,34 @@
namespace sandbox {
+namespace {
+
+DWORD GetObjectSecurityDescriptor(HANDLE handle,
+ SECURITY_INFORMATION security_info,
+ std::vector<char>* security_desc_buffer,
+ PSECURITY_DESCRIPTOR* security_desc) {
+ DWORD last_error = 0;
+ DWORD length_needed = 0;
+
+ ::GetKernelObjectSecurity(handle, security_info, nullptr, 0, &length_needed);
+ last_error = ::GetLastError();
+ if (last_error != ERROR_INSUFFICIENT_BUFFER)
+ return last_error;
+
+ security_desc_buffer->resize(length_needed);
+ *security_desc =
+ reinterpret_cast<PSECURITY_DESCRIPTOR>(security_desc_buffer->data());
+
+ if (!::GetKernelObjectSecurity(handle, security_info, *security_desc,
+ length_needed, &length_needed)) {
+ return ::GetLastError();
+ }
+
+ return ERROR_SUCCESS;
+}
+
+} // namespace
+
DWORD CreateRestrictedToken(TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
@@ -243,31 +271,21 @@ DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level) {
}
DWORD HardenTokenIntegrityLevelPolicy(HANDLE token) {
- DWORD last_error = 0;
- DWORD length_needed = 0;
-
- ::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, nullptr, 0,
- &length_needed);
-
- last_error = ::GetLastError();
- if (last_error != ERROR_INSUFFICIENT_BUFFER)
+ std::vector<char> security_desc_buffer;
+ PSECURITY_DESCRIPTOR security_desc = nullptr;
+ DWORD last_error = GetObjectSecurityDescriptor(
+ token, LABEL_SECURITY_INFORMATION, &security_desc_buffer, &security_desc);
+ if (last_error != ERROR_SUCCESS)
return last_error;
- std::vector<char> security_desc_buffer(length_needed);
- PSECURITY_DESCRIPTOR security_desc =
- reinterpret_cast<PSECURITY_DESCRIPTOR>(&security_desc_buffer[0]);
-
- if (!::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION,
- security_desc, length_needed, &length_needed))
- return ::GetLastError();
-
PACL sacl = nullptr;
BOOL sacl_present = false;
BOOL sacl_defaulted = false;
if (!::GetSecurityDescriptorSacl(security_desc, &sacl_present, &sacl,
- &sacl_defaulted))
+ &sacl_defaulted)) {
return ::GetLastError();
+ }
for (DWORD ace_index = 0; ace_index < sacl->AceCount; ++ace_index) {
PSYSTEM_MANDATORY_LABEL_ACE ace;
@@ -343,7 +361,7 @@ DWORD CreateLowBoxToken(HANDLE base_token,
// Default from NtCreateLowBoxToken is a Primary token.
if (token_type == PRIMARY) {
- token->Set(token_lowbox_handle.Take());
+ *token = std::move(token_lowbox_handle);
return ERROR_SUCCESS;
}
@@ -354,7 +372,23 @@ DWORD CreateLowBoxToken(HANDLE base_token,
return ::GetLastError();
}
- token->Set(dup_handle);
+ // Copy security descriptor from primary token as the new object will have
+ // the DACL from the current token's default DACL.
+ base::win::ScopedHandle token_for_sd(dup_handle);
+ std::vector<char> security_desc_buffer;
+ PSECURITY_DESCRIPTOR security_desc = nullptr;
+ DWORD last_error = GetObjectSecurityDescriptor(
+ token_lowbox_handle.Get(), DACL_SECURITY_INFORMATION,
+ &security_desc_buffer, &security_desc);
+ if (last_error != ERROR_SUCCESS)
+ return last_error;
+
+ if (!::SetKernelObjectSecurity(token_for_sd.Get(), DACL_SECURITY_INFORMATION,
+ security_desc)) {
+ return ::GetLastError();
+ }
+
+ *token = std::move(token_for_sd);
return ERROR_SUCCESS;
}
diff --git a/chromium/sandbox/win/src/sandbox_policy.h b/chromium/sandbox/win/src/sandbox_policy.h
index 4a110fa9d93..46260c3e302 100644
--- a/chromium/sandbox/win/src/sandbox_policy.h
+++ b/chromium/sandbox/win/src/sandbox_policy.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/memory/scoped_refptr.h"
#include "base/strings/string16.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/security_level.h"
@@ -253,8 +254,15 @@ class TargetPolicy {
// Enable OPM API emulation when in Win32k lockdown.
virtual bool GetEnableOPMRedirection() = 0;
- // Configure policy to use an AppContainer profile.
- virtual ResultCode SetAppContainerProfile(AppContainerProfile* profile) = 0;
+ // Configure policy to use an AppContainer profile. |package_name| is the
+ // name of the profile to use. Specifying True for |create_profile| ensures
+ // the profile exists, if set to False process creation will fail if the
+ // profile has not already been created.
+ virtual ResultCode AddAppContainerProfile(const wchar_t* package_name,
+ bool create_profile) = 0;
+
+ // Get the configured AppContainerProfile.
+ virtual scoped_refptr<AppContainerProfile> GetAppContainerProfile() = 0;
protected:
~TargetPolicy() {}
diff --git a/chromium/sandbox/win/src/sandbox_policy_base.cc b/chromium/sandbox/win/src/sandbox_policy_base.cc
index 471fc75a325..d18fe40284d 100644
--- a/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -267,7 +267,7 @@ void PolicyBase::DestroyAlternateDesktop() {
}
ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) {
- if (_app_container_profile)
+ if (app_container_profile_)
return SBOX_ERROR_BAD_PARAMS;
integrity_level_ = integrity_level;
return SBOX_ALL_OK;
@@ -288,7 +288,7 @@ ResultCode PolicyBase::SetLowBox(const wchar_t* sid) {
return SBOX_ERROR_UNSUPPORTED;
DCHECK(sid);
- if (lowbox_sid_ || _app_container_profile)
+ if (lowbox_sid_ || app_container_profile_)
return SBOX_ERROR_BAD_PARAMS;
if (!ConvertStringSidToSid(sid, &lowbox_sid_))
@@ -298,7 +298,7 @@ ResultCode PolicyBase::SetLowBox(const wchar_t* sid) {
}
ResultCode PolicyBase::SetProcessMitigations(MitigationFlags flags) {
- if (!CanSetProcessMitigationsPreStartup(flags))
+ if (app_container_profile_ || !CanSetProcessMitigationsPreStartup(flags))
return SBOX_ERROR_BAD_PARAMS;
mitigations_ = flags;
return SBOX_ALL_OK;
@@ -544,8 +544,10 @@ bool PolicyBase::OnJobEmpty(HANDLE job) {
}
ResultCode PolicyBase::SetDisconnectCsrss() {
-// Does not work on 32-bit.
-#if defined(_WIN64)
+// Does not work on 32-bit, and the ASAN runtime falls over with the
+// CreateThread EAT patch used when this is enabled.
+// See https://crbug.com/783296#c27.
+#if defined(_WIN64) && !defined(ADDRESS_SANITIZER)
if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
is_csrss_connected_ = false;
return AddKernelObjectToClose(L"ALPC Port", nullptr);
@@ -596,21 +598,41 @@ bool PolicyBase::GetEnableOPMRedirection() {
return enable_opm_redirection_;
}
-ResultCode PolicyBase::SetAppContainerProfile(AppContainerProfile* profile) {
+ResultCode PolicyBase::AddAppContainerProfile(const wchar_t* package_name,
+ bool create_profile) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return SBOX_ERROR_UNSUPPORTED;
- DCHECK(profile);
- if (lowbox_sid_ || _app_container_profile ||
+ DCHECK(package_name);
+ if (lowbox_sid_ || app_container_profile_ ||
integrity_level_ != INTEGRITY_LEVEL_LAST)
return SBOX_ERROR_BAD_PARAMS;
- _app_container_profile = profile;
+ if (create_profile) {
+ app_container_profile_ = AppContainerProfileBase::Create(
+ package_name, L"Chrome Sandbox", L"Profile for Chrome Sandbox");
+ } else {
+ app_container_profile_ = AppContainerProfileBase::Open(package_name);
+ }
+ if (!app_container_profile_)
+ return SBOX_ERROR_CREATE_APPCONTAINER_PROFILE;
+ // A bug exists in CreateProcess where enabling an AppContainer profile and
+ // passing a set of mitigation flags will generate ERROR_INVALID_PARAMETER.
+ // Apply best efforts here and convert set mitigations to delayed mitigations.
+ delayed_mitigations_ =
+ mitigations_ & GetAllowedPostStartupProcessMitigations();
+ DCHECK(delayed_mitigations_ == (mitigations_ & ~MITIGATION_SEHOP));
+ mitigations_ = 0;
return SBOX_ALL_OK;
}
scoped_refptr<AppContainerProfile> PolicyBase::GetAppContainerProfile() {
- return _app_container_profile;
+ return GetAppContainerProfileBase();
+}
+
+scoped_refptr<AppContainerProfileBase>
+PolicyBase::GetAppContainerProfileBase() {
+ return app_container_profile_;
}
ResultCode PolicyBase::SetupAllInterceptions(TargetProcess* target) {
diff --git a/chromium/sandbox/win/src/sandbox_policy_base.h b/chromium/sandbox/win/src/sandbox_policy_base.h
index fddea2b2e19..d532221be7e 100644
--- a/chromium/sandbox/win/src/sandbox_policy_base.h
+++ b/chromium/sandbox/win/src/sandbox_policy_base.h
@@ -16,10 +16,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/process/launch.h"
#include "base/strings/string16.h"
#include "base/win/scoped_handle.h"
-#include "sandbox/win/src/app_container_profile.h"
+#include "sandbox/win/src/app_container_profile_base.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/handle_closer.h"
#include "sandbox/win/src/ipc_tags.h"
@@ -73,7 +74,12 @@ class PolicyBase final : public TargetPolicy {
void SetLockdownDefaultDacl() override;
void SetEnableOPMRedirection() override;
bool GetEnableOPMRedirection() override;
- ResultCode SetAppContainerProfile(AppContainerProfile* profile) override;
+ ResultCode AddAppContainerProfile(const wchar_t* package_name,
+ bool create_profile) override;
+ scoped_refptr<AppContainerProfile> GetAppContainerProfile() override;
+
+ // Get the AppContainer profile as its internal type.
+ scoped_refptr<AppContainerProfileBase> GetAppContainerProfileBase();
// Creates a Job object with the level specified in a previous call to
// SetJobLevel().
@@ -102,8 +108,6 @@ class PolicyBase final : public TargetPolicy {
HANDLE GetStdoutHandle();
HANDLE GetStderrHandle();
- scoped_refptr<AppContainerProfile> GetAppContainerProfile();
-
// Returns the list of handles being shared with the target process.
const base::HandlesToInheritVector& GetHandlesBeingShared();
@@ -174,7 +178,7 @@ class PolicyBase final : public TargetPolicy {
base::HandlesToInheritVector handles_to_share_;
bool enable_opm_redirection_;
- scoped_refptr<AppContainerProfile> _app_container_profile;
+ scoped_refptr<AppContainerProfileBase> app_container_profile_;
DISALLOW_COPY_AND_ASSIGN(PolicyBase);
};
diff --git a/chromium/sandbox/win/src/sandbox_types.h b/chromium/sandbox/win/src/sandbox_types.h
index 48ac305df72..e2638996185 100644
--- a/chromium/sandbox/win/src/sandbox_types.h
+++ b/chromium/sandbox/win/src/sandbox_types.h
@@ -107,6 +107,12 @@ enum ResultCode : int {
SBOX_ERROR_CANNOT_WRITE_INTERCEPTION_THUNK = 42,
// Cannot find the base address of the new process.
SBOX_ERROR_CANNOT_FIND_BASE_ADDRESS = 43,
+ // Cannot create the AppContainer profile.
+ SBOX_ERROR_CREATE_APPCONTAINER_PROFILE = 44,
+ // Cannot create the AppContainer as the main executable can't be accessed.
+ SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_ACCESS_CHECK = 45,
+ // Cannot create the AppContainer as adding a capability failed.
+ SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY = 46,
// Placeholder for last item of the enum.
SBOX_ERROR_LAST
};
diff --git a/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp b/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp
index 1e8e0bd9729..d7fd83df001 100644
--- a/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp
+++ b/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp
@@ -109,6 +109,7 @@ InstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte,
(*size)++;
// we got a prefix, so add one and check next byte
ProcessPrefixes(start_byte + 1, size);
+ break;
default:
break; // not a prefix byte
}
diff --git a/chromium/sandbox/win/src/sync_interception.h b/chromium/sandbox/win/src/sync_interception.h
index f7894c63ec4..c21e7ee7b21 100644
--- a/chromium/sandbox/win/src/sync_interception.h
+++ b/chromium/sandbox/win/src/sync_interception.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_SYNC_INTERCEPTION_H_
+#define SANDBOX_WIN_SRC_SYNC_INTERCEPTION_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_SYNC_INTERCEPTION_H__
-#define SANDBOX_SRC_SYNC_INTERCEPTION_H__
-
namespace sandbox {
extern "C" {
@@ -43,4 +43,4 @@ TargetNtOpenEvent(NtOpenEventFunction orig_OpenEvent,
} // namespace sandbox
-#endif // SANDBOX_SRC_SYNC_INTERCEPTION_H__
+#endif // SANDBOX_WIN_SRC_SYNC_INTERCEPTION_H_
diff --git a/chromium/sandbox/win/src/target_interceptions.h b/chromium/sandbox/win/src/target_interceptions.h
index 6350d083681..fac1c65c270 100644
--- a/chromium/sandbox/win/src/target_interceptions.h
+++ b/chromium/sandbox/win/src/target_interceptions.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef SANDBOX_WIN_SRC_TARGET_INTERCEPTIONS_H_
+#define SANDBOX_WIN_SRC_TARGET_INTERCEPTIONS_H_
+
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
-#ifndef SANDBOX_SRC_TARGET_INTERCEPTIONS_H__
-#define SANDBOX_SRC_TARGET_INTERCEPTIONS_H__
-
namespace sandbox {
extern "C" {
@@ -40,4 +40,4 @@ TargetNtUnmapViewOfSection(NtUnmapViewOfSectionFunction orig_UnmapViewOfSection,
} // namespace sandbox
-#endif // SANDBOX_SRC_TARGET_INTERCEPTIONS_H__
+#endif // SANDBOX_WIN_SRC_TARGET_INTERCEPTIONS_H_