Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1209)

Side by Side Diff: mojo/runner/child_process.cc

Issue 1264463005: mandoline sandbox: prewarm libraries before we raise the sandbox. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add security checks to LinuxSandbox::Warmup() Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/runner/BUILD.gn ('k') | mojo/runner/child_process.mojom » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/runner/child_process.h" 5 #include "mojo/runner/child_process.h"
6 6
7 #include "base/base_switches.h" 7 #include "base/base_switches.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
18 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
19 #include "base/synchronization/waitable_event.h" 19 #include "base/synchronization/waitable_event.h"
20 #include "base/thread_task_runner_handle.h" 20 #include "base/thread_task_runner_handle.h"
21 #include "base/threading/thread.h" 21 #include "base/threading/thread.h"
22 #include "base/threading/thread_checker.h" 22 #include "base/threading/thread_checker.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "mojo/common/message_pump_mojo.h" 23 #include "mojo/common/message_pump_mojo.h"
25 #include "mojo/edk/embedder/embedder.h" 24 #include "mojo/edk/embedder/embedder.h"
26 #include "mojo/edk/embedder/platform_channel_pair.h" 25 #include "mojo/edk/embedder/platform_channel_pair.h"
27 #include "mojo/edk/embedder/process_delegate.h" 26 #include "mojo/edk/embedder/process_delegate.h"
28 #include "mojo/edk/embedder/scoped_platform_handle.h" 27 #include "mojo/edk/embedder/scoped_platform_handle.h"
29 #include "mojo/edk/embedder/simple_platform_support.h" 28 #include "mojo/edk/embedder/simple_platform_support.h"
30 #include "mojo/public/cpp/system/core.h" 29 #include "mojo/public/cpp/system/core.h"
31 #include "mojo/runner/child_process.mojom.h" 30 #include "mojo/runner/child_process.mojom.h"
32 #include "mojo/runner/native_application_support.h" 31 #include "mojo/runner/native_application_support.h"
33 #include "mojo/runner/switches.h" 32 #include "mojo/runner/switches.h"
34 33
34 #if defined(OS_LINUX) && !defined(OS_ANDROID)
35 #include "base/rand_util.h"
36 #include "base/sys_info.h"
37 #include "mojo/runner/linux_sandbox.h"
38 #endif
39
35 namespace mojo { 40 namespace mojo {
36 namespace runner { 41 namespace runner {
37 42
38 namespace { 43 namespace {
39 44
40 // Blocker --------------------------------------------------------------------- 45 // Blocker ---------------------------------------------------------------------
41 46
42 // Blocks a thread until another thread unblocks it, at which point it unblocks 47 // Blocks a thread until another thread unblocks it, at which point it unblocks
43 // and runs a closure provided by that thread. 48 // and runs a closure provided by that thread.
44 class Blocker { 49 class Blocker {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 ~ChildControllerImpl() override { 180 ~ChildControllerImpl() override {
176 DCHECK(thread_checker_.CalledOnValidThread()); 181 DCHECK(thread_checker_.CalledOnValidThread());
177 182
178 // TODO(vtl): Pass in the result from |MainMain()|. 183 // TODO(vtl): Pass in the result from |MainMain()|.
179 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED); 184 on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED);
180 } 185 }
181 186
182 // To be executed on the controller thread. Creates the |ChildController|, 187 // To be executed on the controller thread. Creates the |ChildController|,
183 // etc. 188 // etc.
184 static void Init(AppContext* app_context, 189 static void Init(AppContext* app_context,
190 base::NativeLibrary app_library,
185 embedder::ScopedPlatformHandle platform_channel, 191 embedder::ScopedPlatformHandle platform_channel,
186 const Blocker::Unblocker& unblocker) { 192 const Blocker::Unblocker& unblocker) {
187 DCHECK(app_context); 193 DCHECK(app_context);
188 DCHECK(platform_channel.is_valid()); 194 DCHECK(platform_channel.is_valid());
189 195
190 DCHECK(!app_context->controller()); 196 DCHECK(!app_context->controller());
191 197
192 scoped_ptr<ChildControllerImpl> impl( 198 scoped_ptr<ChildControllerImpl> impl(
193 new ChildControllerImpl(app_context, unblocker)); 199 new ChildControllerImpl(app_context, app_library, unblocker));
194 200
195 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( 201 ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel(
196 platform_channel.Pass(), 202 platform_channel.Pass(),
197 base::Bind(&ChildControllerImpl::DidCreateChannel, 203 base::Bind(&ChildControllerImpl::DidCreateChannel,
198 base::Unretained(impl.get())), 204 base::Unretained(impl.get())),
199 base::ThreadTaskRunnerHandle::Get())); 205 base::ThreadTaskRunnerHandle::Get()));
200 206
201 impl->Bind(host_message_pipe.Pass()); 207 impl->Bind(host_message_pipe.Pass());
202 208
203 app_context->set_controller(impl.Pass()); 209 app_context->set_controller(impl.Pass());
204 } 210 }
205 211
206 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); } 212 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
207 213
208 void OnConnectionError() { 214 void OnConnectionError() {
209 // A connection error means the connection to the shell is lost. This is not 215 // A connection error means the connection to the shell is lost. This is not
210 // recoverable. 216 // recoverable.
211 LOG(ERROR) << "Connection error to the shell."; 217 LOG(ERROR) << "Connection error to the shell.";
212 _exit(1); 218 _exit(1);
213 } 219 }
214 220
215 // |ChildController| methods: 221 // |ChildController| methods:
216 void StartApp(const String& app_path, 222 void StartApp(InterfaceRequest<Application> application_request,
217 bool clean_app_path,
218 InterfaceRequest<Application> application_request,
219 const StartAppCallback& on_app_complete) override { 223 const StartAppCallback& on_app_complete) override {
220 DVLOG(2) << "ChildControllerImpl::StartApp(" << app_path << ", ...)";
221 DCHECK(thread_checker_.CalledOnValidThread()); 224 DCHECK(thread_checker_.CalledOnValidThread());
222 225
223 on_app_complete_ = on_app_complete; 226 on_app_complete_ = on_app_complete;
224 unblocker_.Unblock(base::Bind( 227 unblocker_.Unblock(base::Bind(&ChildControllerImpl::StartAppOnMainThread,
225 &ChildControllerImpl::StartAppOnMainThread, 228 base::Unretained(app_library_),
226 base::FilePath::FromUTF8Unsafe(app_path), 229 base::Passed(&application_request)));
227 clean_app_path ? shell::NativeApplicationCleanup::DELETE
228 : shell::NativeApplicationCleanup::DONT_DELETE,
229 base::Passed(&application_request)));
230 } 230 }
231 231
232 void ExitNow(int32_t exit_code) override { 232 void ExitNow(int32_t exit_code) override {
233 DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")"; 233 DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")";
234 _exit(exit_code); 234 _exit(exit_code);
235 } 235 }
236 236
237 private: 237 private:
238 ChildControllerImpl(AppContext* app_context, 238 ChildControllerImpl(AppContext* app_context,
239 base::NativeLibrary app_library,
239 const Blocker::Unblocker& unblocker) 240 const Blocker::Unblocker& unblocker)
240 : app_context_(app_context), 241 : app_context_(app_context),
242 app_library_(app_library),
241 unblocker_(unblocker), 243 unblocker_(unblocker),
242 channel_info_(nullptr), 244 channel_info_(nullptr),
243 binding_(this) { 245 binding_(this) {
244 binding_.set_connection_error_handler([this]() { OnConnectionError(); }); 246 binding_.set_connection_error_handler([this]() { OnConnectionError(); });
245 } 247 }
246 248
247 // Callback for |embedder::CreateChannel()|. 249 // Callback for |embedder::CreateChannel()|.
248 void DidCreateChannel(embedder::ChannelInfo* channel_info) { 250 void DidCreateChannel(embedder::ChannelInfo* channel_info) {
249 DVLOG(2) << "ChildControllerImpl::DidCreateChannel()"; 251 DVLOG(2) << "ChildControllerImpl::DidCreateChannel()";
250 DCHECK(thread_checker_.CalledOnValidThread()); 252 DCHECK(thread_checker_.CalledOnValidThread());
251 channel_info_ = channel_info; 253 channel_info_ = channel_info;
252 } 254 }
253 255
254 static void StartAppOnMainThread( 256 static void StartAppOnMainThread(
255 const base::FilePath& app_path, 257 base::NativeLibrary app_library,
256 shell::NativeApplicationCleanup cleanup,
257 InterfaceRequest<Application> application_request) { 258 InterfaceRequest<Application> application_request) {
258 // TODO(vtl): This is copied from in_process_native_runner.cc. 259 if (!RunNativeApplication(app_library, application_request.Pass())) {
259 DVLOG(2) << "Loading/running Mojo app from " << app_path.value() 260 LOG(ERROR) << "Failure to RunNativeApplication()";
260 << " out of process"; 261 }
261
262 // We intentionally don't unload the native library as its lifetime is the
263 // same as that of the process.
264 base::NativeLibrary app_library = LoadNativeApplication(app_path, cleanup);
265 RunNativeApplication(app_library, application_request.Pass());
266 } 262 }
267 263
268 base::ThreadChecker thread_checker_; 264 base::ThreadChecker thread_checker_;
269 AppContext* const app_context_; 265 AppContext* const app_context_;
266 base::NativeLibrary app_library_;
270 Blocker::Unblocker unblocker_; 267 Blocker::Unblocker unblocker_;
271 StartAppCallback on_app_complete_; 268 StartAppCallback on_app_complete_;
272 269
273 embedder::ChannelInfo* channel_info_; 270 embedder::ChannelInfo* channel_info_;
274 Binding<ChildController> binding_; 271 Binding<ChildController> binding_;
275 272
276 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); 273 DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl);
277 }; 274 };
278 275
279 } // namespace 276 } // namespace
280 277
281 int ChildProcessMain() { 278 int ChildProcessMain() {
282 DVLOG(2) << "ChildProcessMain()"; 279 DVLOG(2) << "ChildProcessMain()";
283 const base::CommandLine& command_line = 280 const base::CommandLine& command_line =
284 *base::CommandLine::ForCurrentProcess(); 281 *base::CommandLine::ForCurrentProcess();
282
283 #if defined(OS_LINUX) && !defined(OS_ANDROID)
284 using sandbox::syscall_broker::BrokerFilePermission;
285 scoped_ptr<mandoline::LinuxSandbox> sandbox;
286 #endif
287 base::NativeLibrary app_library = 0;
288 if (command_line.HasSwitch(switches::kChildProcess)) {
289 // Load the application library before we engage the sandbox.
290 mojo::shell::NativeApplicationCleanup cleanup =
291 command_line.HasSwitch(switches::kDeleteAfterLoad)
292 ? mojo::shell::NativeApplicationCleanup::DELETE
293 : mojo::shell::NativeApplicationCleanup::DONT_DELETE;
294 app_library = mojo::runner::LoadNativeApplication(
295 command_line.GetSwitchValuePath(switches::kChildProcess), cleanup);
296
297 #if defined(OS_LINUX) && !defined(OS_ANDROID)
298 using sandbox::syscall_broker::BrokerFilePermission;
299 scoped_ptr<mandoline::LinuxSandbox> sandbox;
300 if (command_line.HasSwitch(switches::kEnableSandbox)) {
301 // Warm parts of base.
302 base::RandUint64();
303 base::SysInfo::AmountOfPhysicalMemory();
304 base::SysInfo::MaxSharedMemorySize();
305 base::SysInfo::NumberOfProcessors();
306
307 // Do whatever warming that the mojo application wants.
308 typedef void (*SandboxWarmFunction)();
309 SandboxWarmFunction sandbox_warm = reinterpret_cast<SandboxWarmFunction>(
310 base::GetFunctionPointerFromNativeLibrary(app_library,
311 "MojoSandboxWarm"));
312 if (sandbox_warm)
313 sandbox_warm();
314
315 std::vector<BrokerFilePermission> permissions;
316 sandbox.reset(new mandoline::LinuxSandbox(permissions));
317 sandbox->Warmup();
318 sandbox->EngageNamespaceSandbox();
319 sandbox->EngageSeccompSandbox();
320 sandbox->Seal();
321 }
322 #endif
323 }
324
285 embedder::ScopedPlatformHandle platform_channel = 325 embedder::ScopedPlatformHandle platform_channel =
286 embedder::PlatformChannelPair::PassClientHandleFromParentProcess( 326 embedder::PlatformChannelPair::PassClientHandleFromParentProcess(
287 command_line); 327 command_line);
288 CHECK(platform_channel.is_valid()); 328 CHECK(platform_channel.is_valid());
289 329
290 DCHECK(!base::MessageLoop::current()); 330 DCHECK(!base::MessageLoop::current());
291 331
292 AppContext app_context; 332 AppContext app_context;
293 app_context.Init(); 333 app_context.Init();
294 334
295 Blocker blocker; 335 Blocker blocker;
296 app_context.controller_runner()->PostTask( 336 app_context.controller_runner()->PostTask(
297 FROM_HERE, 337 FROM_HERE,
298 base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context), 338 base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context),
299 base::Passed(&platform_channel), blocker.GetUnblocker())); 339 base::Unretained(app_library), base::Passed(&platform_channel),
340 blocker.GetUnblocker()));
300 // This will block, then run whatever the controller wants. 341 // This will block, then run whatever the controller wants.
301 blocker.Block(); 342 blocker.Block();
302 343
303 app_context.Shutdown(); 344 app_context.Shutdown();
304 345
305 return 0; 346 return 0;
306 } 347 }
307 348
308 } // namespace runner 349 } // namespace runner
309 } // namespace mojo 350 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/runner/BUILD.gn ('k') | mojo/runner/child_process.mojom » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698