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