| Index: components/nacl/loader/nacl_helper_linux.cc
|
| diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc
|
| index a7c6615e51b11973b9c98d6d1f762de23d48fa31..68d0ff66ce6d93fa48574360e22a17e2fc85bf1c 100644
|
| --- a/components/nacl/loader/nacl_helper_linux.cc
|
| +++ b/components/nacl/loader/nacl_helper_linux.cc
|
| @@ -32,17 +32,13 @@
|
| #include "base/rand_util.h"
|
| #include "components/nacl/common/nacl_switches.h"
|
| #include "components/nacl/loader/nacl_listener.h"
|
| -#include "components/nacl/loader/nacl_sandbox_linux.h"
|
| -#include "components/nacl/loader/nonsfi/nonsfi_sandbox.h"
|
| +#include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h"
|
| #include "content/public/common/content_descriptors.h"
|
| #include "content/public/common/zygote_fork_delegate_linux.h"
|
| #include "crypto/nss_util.h"
|
| #include "ipc/ipc_descriptors.h"
|
| #include "ipc/ipc_switches.h"
|
| -#include "sandbox/linux/services/credentials.h"
|
| #include "sandbox/linux/services/libc_urandom_override.h"
|
| -#include "sandbox/linux/services/thread_helpers.h"
|
| -#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
|
|
|
| namespace {
|
|
|
| @@ -51,69 +47,6 @@ struct NaClLoaderSystemInfo {
|
| long number_of_cores;
|
| };
|
|
|
| -// This is a poor man's check on whether we are sandboxed.
|
| -bool IsSandboxed() {
|
| - int proc_fd = open("/proc/self/exe", O_RDONLY);
|
| - if (proc_fd >= 0) {
|
| - close(proc_fd);
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void InitializeLayerOneSandbox() {
|
| - // Check that IsSandboxed() works. We should not be sandboxed at this point.
|
| - CHECK(!IsSandboxed()) << "Unexpectedly sandboxed!";
|
| - scoped_ptr<sandbox::SetuidSandboxClient>
|
| - setuid_sandbox_client(sandbox::SetuidSandboxClient::Create());
|
| - PCHECK(0 == IGNORE_EINTR(close(
|
| - setuid_sandbox_client->GetUniqueToChildFileDescriptor())));
|
| - const bool suid_sandbox_child = setuid_sandbox_client->IsSuidSandboxChild();
|
| - const bool is_init_process = 1 == getpid();
|
| - CHECK_EQ(is_init_process, suid_sandbox_child);
|
| -
|
| - if (suid_sandbox_child) {
|
| - // Make sure that no directory file descriptor is open, as it would bypass
|
| - // the setuid sandbox model.
|
| - sandbox::Credentials credentials;
|
| - CHECK(!credentials.HasOpenDirectory(-1));
|
| -
|
| - // Get sandboxed.
|
| - CHECK(setuid_sandbox_client->ChrootMe());
|
| - CHECK(IsSandboxed());
|
| - }
|
| -}
|
| -
|
| -void InitializeLayerTwoSandbox(bool uses_nonsfi_mode) {
|
| - if (uses_nonsfi_mode) {
|
| - const bool can_be_no_sandbox = CommandLine::ForCurrentProcess()->HasSwitch(
|
| - switches::kNaClDangerousNoSandboxNonSfi);
|
| - const bool setuid_sandbox_enabled = IsSandboxed();
|
| - if (!setuid_sandbox_enabled) {
|
| - if (can_be_no_sandbox)
|
| - LOG(ERROR) << "DANGEROUS: Running non-SFI NaCl without SUID sandbox!";
|
| - else
|
| - LOG(FATAL) << "SUID sandbox is mandatory for non-SFI NaCl";
|
| - }
|
| - const bool bpf_sandbox_initialized = nacl::nonsfi::InitializeBPFSandbox();
|
| - if (!bpf_sandbox_initialized) {
|
| - if (can_be_no_sandbox) {
|
| - LOG(ERROR)
|
| - << "DANGEROUS: Running non-SFI NaCl without seccomp-bpf sandbox!";
|
| - } else {
|
| - LOG(FATAL) << "Could not initialize NaCl's second "
|
| - << "layer sandbox (seccomp-bpf) for non-SFI mode.";
|
| - }
|
| - }
|
| - } else {
|
| - const bool bpf_sandbox_initialized = InitializeBPFSandbox();
|
| - if (!bpf_sandbox_initialized) {
|
| - LOG(ERROR) << "Could not initialize NaCl's second "
|
| - << "layer sandbox (seccomp-bpf) for SFI mode.";
|
| - }
|
| - }
|
| -}
|
| -
|
| // Replace |file_descriptor| with the reading end of a closed pipe.
|
| void ReplaceFDWithDummy(int file_descriptor) {
|
| // Make sure that file_descriptor is an open descriptor.
|
| @@ -130,7 +63,9 @@ void ReplaceFDWithDummy(int file_descriptor) {
|
| // if (!child) {
|
| void BecomeNaClLoader(const std::vector<int>& child_fds,
|
| const NaClLoaderSystemInfo& system_info,
|
| - bool uses_nonsfi_mode) {
|
| + bool uses_nonsfi_mode,
|
| + nacl::NaClSandbox* nacl_sandbox) {
|
| + DCHECK(nacl_sandbox);
|
| VLOG(1) << "NaCl loader: setting up IPC descriptor";
|
| // Close or shutdown IPC channels that we don't need anymore.
|
| PCHECK(0 == IGNORE_EINTR(close(kNaClZygoteDescriptor)));
|
| @@ -149,7 +84,12 @@ void BecomeNaClLoader(const std::vector<int>& child_fds,
|
| ReplaceFDWithDummy(sandbox_ipc_channel);
|
| }
|
|
|
| - InitializeLayerTwoSandbox(uses_nonsfi_mode);
|
| + // Finish layer-1 sandbox initialization and initialize the layer-2 sandbox.
|
| + CHECK(!nacl_sandbox->HasOpenDirectory());
|
| + nacl_sandbox->InitializeLayerTwoSandbox(uses_nonsfi_mode);
|
| + nacl_sandbox->SealLayerOneSandbox();
|
| + nacl_sandbox->CheckSandboxingStateWithPolicy();
|
| +
|
| base::GlobalDescriptors::GetInstance()->Set(
|
| kPrimaryIPCChannel,
|
| child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]);
|
| @@ -167,6 +107,7 @@ void BecomeNaClLoader(const std::vector<int>& child_fds,
|
| void ChildNaClLoaderInit(const std::vector<int>& child_fds,
|
| const NaClLoaderSystemInfo& system_info,
|
| bool uses_nonsfi_mode,
|
| + nacl::NaClSandbox* nacl_sandbox,
|
| const std::string& channel_id) {
|
| const int parent_fd = child_fds[content::ZygoteForkDelegate::kParentFDIndex];
|
| const int dummy_fd = child_fds[content::ZygoteForkDelegate::kDummyFDIndex];
|
| @@ -199,7 +140,7 @@ void ChildNaClLoaderInit(const std::vector<int>& child_fds,
|
| if (IGNORE_EINTR(close(parent_fd)) != 0)
|
| LOG(ERROR) << "close(parent_fd) failed";
|
| if (validack) {
|
| - BecomeNaClLoader(child_fds, system_info, uses_nonsfi_mode);
|
| + BecomeNaClLoader(child_fds, system_info, uses_nonsfi_mode, nacl_sandbox);
|
| } else {
|
| LOG(ERROR) << "Failed to synch with zygote";
|
| }
|
| @@ -211,6 +152,7 @@ void ChildNaClLoaderInit(const std::vector<int>& child_fds,
|
| // content/browser/zygote_main_linux.cc:ForkWithRealPid()
|
| bool HandleForkRequest(const std::vector<int>& child_fds,
|
| const NaClLoaderSystemInfo& system_info,
|
| + nacl::NaClSandbox* nacl_sandbox,
|
| PickleIterator* input_iter,
|
| Pickle* output_pickle) {
|
| bool uses_nonsfi_mode;
|
| @@ -238,7 +180,8 @@ bool HandleForkRequest(const std::vector<int>& child_fds,
|
| }
|
|
|
| if (child_pid == 0) {
|
| - ChildNaClLoaderInit(child_fds, system_info, uses_nonsfi_mode, channel_id);
|
| + ChildNaClLoaderInit(
|
| + child_fds, system_info, uses_nonsfi_mode, nacl_sandbox, channel_id);
|
| NOTREACHED();
|
| }
|
|
|
| @@ -293,14 +236,15 @@ bool HonorRequestAndReply(int reply_fd,
|
| int command_type,
|
| const std::vector<int>& attached_fds,
|
| const NaClLoaderSystemInfo& system_info,
|
| + nacl::NaClSandbox* nacl_sandbox,
|
| PickleIterator* input_iter) {
|
| Pickle write_pickle;
|
| bool have_to_reply = false;
|
| // Commands must write anything to send back to |write_pickle|.
|
| switch (command_type) {
|
| case nacl::kNaClForkRequest:
|
| - have_to_reply = HandleForkRequest(attached_fds, system_info,
|
| - input_iter, &write_pickle);
|
| + have_to_reply = HandleForkRequest(
|
| + attached_fds, system_info, nacl_sandbox, input_iter, &write_pickle);
|
| break;
|
| case nacl::kNaClGetTerminationStatusRequest:
|
| have_to_reply =
|
| @@ -324,14 +268,15 @@ bool HonorRequestAndReply(int reply_fd,
|
| // Read a request from the Zygote from |zygote_ipc_fd| and handle it.
|
| // Die on EOF from |zygote_ipc_fd|.
|
| bool HandleZygoteRequest(int zygote_ipc_fd,
|
| - const NaClLoaderSystemInfo& system_info) {
|
| + const NaClLoaderSystemInfo& system_info,
|
| + nacl::NaClSandbox* nacl_sandbox) {
|
| std::vector<int> fds;
|
| char buf[kNaClMaxIPCMessageLength];
|
| const ssize_t msglen = UnixDomainSocket::RecvMsg(zygote_ipc_fd,
|
| &buf, sizeof(buf), &fds);
|
| // If the Zygote has started handling requests, we should be sandboxed via
|
| // the setuid sandbox.
|
| - if (!IsSandboxed()) {
|
| + if (!nacl_sandbox->layer_one_enabled()) {
|
| LOG(ERROR) << "NaCl helper process running without a sandbox!\n"
|
| << "Most likely you need to configure your SUID sandbox "
|
| << "correctly";
|
| @@ -352,8 +297,8 @@ bool HandleZygoteRequest(int zygote_ipc_fd,
|
| LOG(ERROR) << "Unable to read command from Zygote";
|
| return false;
|
| }
|
| - return HonorRequestAndReply(zygote_ipc_fd, command_type, fds, system_info,
|
| - &read_iter);
|
| + return HonorRequestAndReply(
|
| + zygote_ipc_fd, command_type, fds, system_info, nacl_sandbox, &read_iter);
|
| }
|
|
|
| static const char kNaClHelperReservedAtZero[] = "reserved_at_zero";
|
| @@ -470,13 +415,16 @@ int main(int argc, char* argv[]) {
|
|
|
| CheckRDebug(argv[0]);
|
|
|
| + scoped_ptr<nacl::NaClSandbox> nacl_sandbox(new nacl::NaClSandbox);
|
| // Make sure that the early initialization did not start any spurious
|
| // threads.
|
| #if !defined(THREAD_SANITIZER)
|
| - CHECK(sandbox::ThreadHelpers::IsSingleThreaded(-1));
|
| + CHECK(nacl_sandbox->IsSingleThreaded());
|
| #endif
|
|
|
| - InitializeLayerOneSandbox();
|
| + const bool is_init_process = 1 == getpid();
|
| + nacl_sandbox->InitializeLayerOneSandbox();
|
| + CHECK_EQ(is_init_process, nacl_sandbox->layer_one_enabled());
|
|
|
| const std::vector<int> empty;
|
| // Send the zygote a message to let it know we are ready to help
|
| @@ -488,8 +436,8 @@ int main(int argc, char* argv[]) {
|
|
|
| // Now handle requests from the Zygote.
|
| while (true) {
|
| - bool request_handled = HandleZygoteRequest(kNaClZygoteDescriptor,
|
| - system_info);
|
| + bool request_handled = HandleZygoteRequest(
|
| + kNaClZygoteDescriptor, system_info, nacl_sandbox.get());
|
| // Do not turn this into a CHECK() without thinking about robustness
|
| // against malicious IPC requests.
|
| DCHECK(request_handled);
|
|
|