1 // Copyright 2019 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 "chrome/chrome_cleaner/engines/target/sandbox_setup.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/base_paths.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/files/file_path.h"
14 #include "base/path_service.h"
15 #include "base/run_loop.h"
16 #include "base/task/single_thread_task_executor.h"
17 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
18 #include "chrome/chrome_cleaner/engines/target/engine_commands_impl.h"
19 #include "chrome/chrome_cleaner/engines/target/libraries.h"
20 #include "chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h"
21 #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h"
22 #include "chrome/chrome_cleaner/mojom/engine_sandbox.mojom.h"
23 #include "chrome/chrome_cleaner/os/early_exit.h"
24 #include "mojo/public/cpp/bindings/pending_receiver.h"
25
26 namespace chrome_cleaner {
27
28 namespace {
29
30 class EngineMojoSandboxTargetHooks : public MojoSandboxTargetHooks {
31 public:
32 EngineMojoSandboxTargetHooks(scoped_refptr<EngineDelegate> engine_delegate,
33 MojoTaskRunner* mojo_task_runner);
34 ~EngineMojoSandboxTargetHooks() override;
35
36 void BindEngineCommandsReceiver(
37 mojo::PendingReceiver<mojom::EngineCommands> receiver);
38
39 // SandboxTargetHooks
40
41 ResultCode TargetDroppedPrivileges(
42 const base::CommandLine& command_line) override;
43
44 private:
45 scoped_refptr<EngineDelegate> engine_delegate_;
46 MojoTaskRunner* mojo_task_runner_;
47
48 base::SingleThreadTaskExecutor single_thread_task_executor_;
49
50 std::unique_ptr<EngineCommandsImpl> engine_commands_impl_;
51
52 DISALLOW_COPY_AND_ASSIGN(EngineMojoSandboxTargetHooks);
53 };
54
EngineMojoSandboxTargetHooks(scoped_refptr<EngineDelegate> engine_delegate,MojoTaskRunner * mojo_task_runner)55 EngineMojoSandboxTargetHooks::EngineMojoSandboxTargetHooks(
56 scoped_refptr<EngineDelegate> engine_delegate,
57 MojoTaskRunner* mojo_task_runner)
58 : engine_delegate_(engine_delegate), mojo_task_runner_(mojo_task_runner) {}
59
~EngineMojoSandboxTargetHooks()60 EngineMojoSandboxTargetHooks::~EngineMojoSandboxTargetHooks() {
61 mojo_task_runner_->PostTask(
62 FROM_HERE, base::BindOnce(
63 [](std::unique_ptr<EngineCommandsImpl> commands) {
64 commands.reset();
65 },
66 std::move(engine_commands_impl_)));
67 }
68
TargetDroppedPrivileges(const base::CommandLine & command_line)69 ResultCode EngineMojoSandboxTargetHooks::TargetDroppedPrivileges(
70 const base::CommandLine& command_line) {
71 // Connect to the Mojo message pipe from the parent process.
72 mojo::PendingReceiver<mojom::EngineCommands> receiver(
73 ExtractSandboxMessagePipe(command_line));
74
75 // This loop will run forever. Once the communication channel with the broker
76 // process is broken, mojo error handler will abort this process.
77 base::RunLoop run_loop;
78 mojo_task_runner_->PostTask(
79 FROM_HERE,
80 base::BindOnce(&EngineMojoSandboxTargetHooks::BindEngineCommandsReceiver,
81 base::Unretained(this), std::move(receiver)));
82
83 run_loop.Run();
84 return RESULT_CODE_SUCCESS;
85 }
86
BindEngineCommandsReceiver(mojo::PendingReceiver<mojom::EngineCommands> receiver)87 void EngineMojoSandboxTargetHooks::BindEngineCommandsReceiver(
88 mojo::PendingReceiver<mojom::EngineCommands> receiver) {
89 // If the connection dies, the parent process has terminated unexpectedly.
90 // Exit immediately. The child process should be killed automatically if the
91 // parent dies, so this is just a fallback. The exit code is arbitrary since
92 // there's no parent process to collect and report it.
93 auto error_handler = base::BindOnce(&EarlyExit, 1);
94
95 engine_commands_impl_ = std::make_unique<EngineCommandsImpl>(
96 std::move(engine_delegate_), std::move(receiver), mojo_task_runner_,
97 std::move(error_handler));
98 }
99
100 } // namespace
101
RunEngineSandboxTarget(scoped_refptr<EngineDelegate> engine_delegate,const base::CommandLine & command_line,sandbox::TargetServices * sandbox_target_services)102 ResultCode RunEngineSandboxTarget(
103 scoped_refptr<EngineDelegate> engine_delegate,
104 const base::CommandLine& command_line,
105 sandbox::TargetServices* sandbox_target_services) {
106 // Extract the libraries to the same directory as the executable.
107 base::FilePath extraction_dir;
108 CHECK(base::PathService::Get(base::DIR_EXE, &extraction_dir));
109 if (!LoadAndValidateLibraries(engine_delegate->engine(), extraction_dir)) {
110 NOTREACHED() << "Binary signature validation failed";
111 return RESULT_CODE_SIGNATURE_VERIFICATION_FAILED;
112 }
113
114 scoped_refptr<MojoTaskRunner> sandbox_mojo_task_runner =
115 MojoTaskRunner::Create();
116
117 EngineMojoSandboxTargetHooks mojo_target_hooks(
118 std::move(engine_delegate), sandbox_mojo_task_runner.get());
119 return RunSandboxTarget(command_line, sandbox_target_services,
120 &mojo_target_hooks);
121 }
122
123 } // namespace chrome_cleaner
124