| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "services/service_manager/runner/host/linux_sandbox.h" |
| 6 |
| 7 #include <fcntl.h> |
| 8 #include <sys/syscall.h> |
| 9 #include <utility> |
| 10 |
| 11 #include "base/bind.h" |
| 12 #include "base/debug/leak_annotations.h" |
| 13 #include "base/macros.h" |
| 14 #include "base/posix/eintr_wrapper.h" |
| 15 #include "base/rand_util.h" |
| 16 #include "base/sys_info.h" |
| 17 #include "sandbox/linux/bpf_dsl/policy.h" |
| 18 #include "sandbox/linux/bpf_dsl/trap_registry.h" |
| 19 #include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h" |
| 20 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" |
| 21 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" |
| 22 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" |
| 23 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 24 #include "sandbox/linux/services/credentials.h" |
| 25 #include "sandbox/linux/services/namespace_sandbox.h" |
| 26 #include "sandbox/linux/services/proc_util.h" |
| 27 #include "sandbox/linux/services/thread_helpers.h" |
| 28 |
| 29 using sandbox::syscall_broker::BrokerFilePermission; |
| 30 |
| 31 namespace service_manager { |
| 32 |
| 33 namespace { |
| 34 |
| 35 intptr_t SandboxSIGSYSHandler(const struct sandbox::arch_seccomp_data& args, |
| 36 void* aux) { |
| 37 RAW_CHECK(aux); |
| 38 const sandbox::syscall_broker::BrokerProcess* broker_process = |
| 39 static_cast<const sandbox::syscall_broker::BrokerProcess*>(aux); |
| 40 switch (args.nr) { |
| 41 #if !defined(__aarch64__) |
| 42 case __NR_access: |
| 43 return broker_process->Access(reinterpret_cast<const char*>(args.args[0]), |
| 44 static_cast<int>(args.args[1])); |
| 45 case __NR_open: |
| 46 return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), |
| 47 static_cast<int>(args.args[1])); |
| 48 #endif |
| 49 case __NR_faccessat: |
| 50 if (static_cast<int>(args.args[0]) == AT_FDCWD) { |
| 51 return broker_process->Access( |
| 52 reinterpret_cast<const char*>(args.args[1]), |
| 53 static_cast<int>(args.args[2])); |
| 54 } else { |
| 55 return -EPERM; |
| 56 } |
| 57 case __NR_openat: |
| 58 // Allow using openat() as open(). |
| 59 if (static_cast<int>(args.args[0]) == AT_FDCWD) { |
| 60 return broker_process->Open(reinterpret_cast<const char*>(args.args[1]), |
| 61 static_cast<int>(args.args[2])); |
| 62 } else { |
| 63 return -EPERM; |
| 64 } |
| 65 default: |
| 66 RAW_CHECK(false); |
| 67 return -ENOSYS; |
| 68 } |
| 69 } |
| 70 |
| 71 class SandboxPolicy : public sandbox::BaselinePolicy { |
| 72 public: |
| 73 explicit SandboxPolicy(sandbox::syscall_broker::BrokerProcess* broker_process) |
| 74 : broker_process_(broker_process) {} |
| 75 ~SandboxPolicy() override {} |
| 76 |
| 77 // Overridden from sandbox::bpf_dsl::Policy: |
| 78 sandbox::bpf_dsl::ResultExpr EvaluateSyscall(int sysno) const override { |
| 79 // This policy is only advisory/for noticing FS access for the moment. |
| 80 switch (sysno) { |
| 81 #if !defined(__aarch64__) |
| 82 case __NR_access: |
| 83 case __NR_open: |
| 84 #endif |
| 85 case __NR_faccessat: |
| 86 case __NR_openat: |
| 87 return sandbox::bpf_dsl::Trap(SandboxSIGSYSHandler, broker_process_); |
| 88 case __NR_sched_getaffinity: |
| 89 return sandbox::RestrictSchedTarget(policy_pid(), sysno); |
| 90 case __NR_ftruncate: |
| 91 #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \ |
| 92 defined(__aarch64__) |
| 93 // Per #ifdefs in |
| 94 // content/common/sandbox_linux/bpf_renderer_policy_linux.cc |
| 95 case __NR_getrlimit: |
| 96 #endif |
| 97 #if defined(__i386__) || defined(__arm__) |
| 98 case __NR_ugetrlimit: |
| 99 #endif |
| 100 case __NR_uname: |
| 101 #if defined(__arm__) || defined(__x86_64__) || defined(__mips__) |
| 102 case __NR_getsockopt: |
| 103 case __NR_setsockopt: |
| 104 #endif |
| 105 return sandbox::bpf_dsl::Allow(); |
| 106 } |
| 107 |
| 108 return BaselinePolicy::EvaluateSyscall(sysno); |
| 109 } |
| 110 |
| 111 private: |
| 112 // Not owned. |
| 113 const sandbox::syscall_broker::BrokerProcess* broker_process_; |
| 114 DISALLOW_COPY_AND_ASSIGN(SandboxPolicy); |
| 115 }; |
| 116 |
| 117 } // namespace |
| 118 |
| 119 LinuxSandbox::LinuxSandbox(const std::vector<BrokerFilePermission>& permissions) |
| 120 : broker_(new sandbox::syscall_broker::BrokerProcess(EPERM, permissions)) { |
| 121 CHECK(broker_->Init( |
| 122 base::Bind<bool (*)()>(&sandbox::Credentials::DropAllCapabilities))); |
| 123 policy_.reset(new SandboxPolicy(broker_.get())); |
| 124 } |
| 125 |
| 126 LinuxSandbox::~LinuxSandbox() {} |
| 127 |
| 128 void LinuxSandbox::Warmup() { |
| 129 proc_fd_ = sandbox::ProcUtil::OpenProc(); |
| 130 warmed_up_ = true; |
| 131 |
| 132 // Verify that we haven't started threads or grabbed directory file |
| 133 // descriptors. |
| 134 sandbox::ThreadHelpers::AssertSingleThreaded(proc_fd_.get()); |
| 135 CHECK(!sandbox::ProcUtil::HasOpenDirectory(proc_fd_.get())); |
| 136 } |
| 137 |
| 138 void LinuxSandbox::EngageNamespaceSandbox() { |
| 139 CHECK(warmed_up_); |
| 140 CHECK_EQ(1, getpid()); |
| 141 CHECK(sandbox::NamespaceSandbox::InNewPidNamespace()); |
| 142 CHECK(sandbox::Credentials::MoveToNewUserNS()); |
| 143 CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_.get())); |
| 144 CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd_.get())); |
| 145 } |
| 146 |
| 147 void LinuxSandbox::EngageSeccompSandbox() { |
| 148 CHECK(warmed_up_); |
| 149 sandbox::SandboxBPF sandbox(policy_.release()); |
| 150 base::ScopedFD proc_fd(HANDLE_EINTR( |
| 151 openat(proc_fd_.get(), ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); |
| 152 CHECK(proc_fd.is_valid()); |
| 153 sandbox.SetProcFd(std::move(proc_fd)); |
| 154 CHECK( |
| 155 sandbox.StartSandbox(sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED)) |
| 156 << "Starting the process with a sandbox failed. Missing kernel support."; |
| 157 |
| 158 // The Broker is now bound to this process and should only be destroyed when |
| 159 // the process exits or is killed. |
| 160 sandbox::syscall_broker::BrokerProcess* leaked_broker = broker_.release(); |
| 161 ALLOW_UNUSED_LOCAL(leaked_broker); |
| 162 ANNOTATE_LEAKING_OBJECT_PTR(leaked_broker); |
| 163 } |
| 164 |
| 165 void LinuxSandbox::Seal() { |
| 166 proc_fd_.reset(); |
| 167 } |
| 168 |
| 169 } // namespace service_manager |
| OLD | NEW |