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/shell/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 shell { | |
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 shell | |
OLD | NEW |