The purpose of the Chrome Cleanup Tool and Software Reporter Tool is to scan files that are found on users' machines for the presence of Unwanted Software (UwS) that could effect chrome. These files are untrusted inputs so, according to the Rule of 2 all code that parses them must run in a sandbox.
Sandboxes are implemented using the chromium sandbox library.
The tool has separate sandboxes for each type of parsing that's done on untrusted files:
The code for each sandbox is split into two subdirectories, broker
and target
, for easier auditing.
broker
contains code that runs in the broker process.target
contains code that runs in the target process.The target process communicates with the broker process using Mojo.
The main entry point to create a sandbox is SpawnSandbox
in ipc/sandbox.cc. Call this with a SandboxSetupHooks
subclass.
SandboxSetupHooks
to provide custom behaviour for each sandbox type, such as instantiating an IPC channel or adding custom flags to the sandbox command-line.SandboxSetupHooks
subclass is paired with a SandboxTargetHooks
subclass that knows how to deal with the custom behaviour, eg. connect to the IPC channel.MojoSandboxSetupHooks
and MojoSandboxTargetHooks
subclasses contain common code to set up a Mojo IPC connection. Override them to provide details of the Mojo interface to use with the connection. See below for more details.SpawnSandbox
will:
--sandboxed-process-id=<sandbox type>
to the command-line that will be used for the target process.hooks->UpdateSandboxPolicy
. You can override this to alter the policy and command-line.GetTargetServices
returns non-null).hooks->TargetSpawned
with handles to the new process and to its main thread.hooks->TargetResumed
.If any step fails the function calls hooks->SetupFailed
.
You will probably want to set up a Mojo IPC channel to your target process. To do this:
SandboxSetupHooks
.mojo::Remote<SomeMojoInterface>
. This acts like a pointer-to-SomeMojoInterface. Methods called through this “pointer” will be marshalled over Mojo IPC to the target process, where SomeMojoInterface is implemented.mojo::Remote<mojom::ZipArchiver>
defined in zip_archiver.mojom.UpdateSandboxPolicy
to:MojoSandboxSetupHooks::SetupSandboxMessagePipe
, which returns a handle to the Mojo pipe.mojo::PendingRemote<SomeMojoInterface>
that wraps the pipe handle.PendingRemote
to mojo::Remote<SomeMojoInterface>::Bind
. Now the remote is bound to the Mojo pipe.ZipArchiverSandboxSetupHooks::TakeZipArchiverRemote
.Note: All methods on a mojo::Remote
, including the destructor, need to be called from the same sequence. For legacy reasons chrome_cleaner uses an object called MojoTaskRunner for all remotes.
The easy way to ensure that all methods are called on the same sequence would be to use SequenceBound but this code predates it, so instead there are lots of explicit calls to PostTask
and OnTaskRunnerDeleter
.
Near the start of main, the app checks if GetTargetServices
returns non-null. If so, it‘s running in the sandbox. (The "Resume the target process’s main thread" step of SpawnSandbox
has just finished.) At this point the sandboxed process still has many privileges.
The app then:
--sandboxed-process-id
command-line switch to see which type of sandbox to start.RunSandboxTarget
in ipc/sandbox.cc, which will:TargetService
.hooks->TargetStartedWithHighPrivileges
. Override this to do any setup that needs privileges,TargetService::LowerToken
to drop the remaining privileges.hooks->TargetDroppedPrivileges
. Override this to do the main processing for the sandbox.When RunSandboxTarget
returns, the sandboxed process exits.
hooks->TargetDroppedPrivileges
, servicing requests sent over IPC from the broker process. The broker will kill all target processes when it exits.To connect to a Mojo IPC channel in the target:
SandboxTargetHooks
.MojoSandboxSetupHooks
that creates a mojo::Remote<SomeMojoInterface>
.SomeMojoInterface
. Traditionally this is done in a class called SomeMojoInterfaceImpl
.mojo::Receiver<SomeMojoInterface>
.mojom::ZipArchiver
is implemented in ZipArchiverImpl, and it owns a mojo::Receiver<mojom::ZipArchier>
.target
subdir to enforce that the implementation is only used in the target process.TargetDroppedPrivileges
to:MojoSandboxTargetHooks::ExtractSandboxMessagePipe
, which returns a handle to the Mojo pipe that was created in MojoSandboxSetupHooks::UpdateSandboxPolicy
.mojo::PendingReceiver<SomeMojoInterface>
that wraps the pipe handle.SomeMojoInterfaceImpl
, assigning the PendingReceiver
to the Receiver
.SomeMojoInterfaceImpl
to the IPC pipe, so all calls to methods on the mojo::Remote<SomeMojoInterface>
in the broker process are marshalled across the pipe and invoke the corresponding method on the SomeMojoInterfaceImpl
.RunLoop::Run
to loop until the process is killed. Mojo will do the rest.