
This is a followup to [1]. [1] https://chromium-review.googlesource.com/c/chromium/src/+/1974901 TBR=sky Change-Id: I442ffe121378607bdc5e1b16c081b8d66b138955 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1980900 Reviewed-by: Thomas Anderson <thomasanderson@chromium.org> Commit-Queue: Thomas Anderson <thomasanderson@chromium.org> Cr-Commit-Position: refs/heads/master@{#727226}
130 lines
5.6 KiB
Markdown
130 lines
5.6 KiB
Markdown
# Linux `SUID` Sandbox
|
|
|
|
*IMPORTANT NOTE: The Linux SUID sandbox is almost but not completely removed.
|
|
See https://bugs.chromium.org/p/chromium/issues/detail?id=598454
|
|
This page is mostly out-of-date.*
|
|
|
|
With [r20110](https://crrev.com/20110), Chromium on Linux can now sandbox its
|
|
renderers using a `SUID` helper binary. This is one of
|
|
[our layer-1 sandboxing solutions](sandboxing.md).
|
|
|
|
## `SUID` helper executable
|
|
|
|
The `SUID` helper binary is called `chrome_sandbox` and you must build it
|
|
separately from the main 'chrome' target. Chrome now just assumes it's next
|
|
to the executable in the same directory. You can also control its path
|
|
by CHROME_DEVEL_SANDBOX environment variable.
|
|
|
|
In order for the sandbox to be used, the following conditions must be met:
|
|
|
|
* The sandbox binary must be executable by the Chromium process.
|
|
* It must be `SUID` and executable by other.
|
|
|
|
If these conditions are met then the sandbox binary is used to launch the zygote
|
|
process. Once the zygote has started, it asks a helper process to chroot it to a
|
|
temp directory.
|
|
|
|
## `CLONE_NEWPID` method
|
|
|
|
The sandbox does three things to restrict the authority of a sandboxed process.
|
|
The `SUID` helper is responsible for the first two:
|
|
|
|
* The `SUID` helper chroots the process. This takes away access to the
|
|
filesystem namespace.
|
|
* The `SUID` helper puts the process in a PID namespace using the
|
|
`CLONE_NEWPID` option to
|
|
[clone()](http://www.kernel.org/doc/man-pages/online/pages/man2/clone.2.html).
|
|
This stops the sandboxed process from being able to `ptrace()` or `kill()`
|
|
unsandboxed processes.
|
|
|
|
In addition:
|
|
|
|
* The [Linux Zygote](zygote.md) startup code sets the process to be
|
|
_undumpable_ using
|
|
[prctl()](http://www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html).
|
|
This stops sandboxed processes from being able to `ptrace()` each other.
|
|
More specifically, it stops the sandboxed process from being `ptrace()`'d by
|
|
any other process. This can be switched off with the
|
|
`--allow-sandbox-debugging` option.
|
|
|
|
Limitations:
|
|
|
|
* Not all kernel versions support `CLONE_NEWPID`. If the `SUID` helper is run
|
|
on a kernel that does not support `CLONE_NEWPID`, it will ignore the problem
|
|
without a warning, but the protection offered by the sandbox will be
|
|
substantially reduced. See LinuxPidNamespaceSupport for how to test whether
|
|
your system supports PID namespaces.
|
|
* This does not restrict network access.
|
|
* This does not prevent processes within a given sandbox from sending each
|
|
other signals or killing each other.
|
|
* Setting a process to be undumpable is not irreversible. A sandboxed process
|
|
can make itself dumpable again, opening itself up to being taken over by
|
|
another process (either unsandboxed or within the same sandbox).
|
|
* Breakpad (the crash reporting tool) makes use of this. If a process
|
|
crashes, Breakpad makes it dumpable in order to use ptrace() to halt
|
|
threads and capture the process's state at the time of the crash. This
|
|
opens a small window of vulnerability.
|
|
|
|
## `setuid()` method
|
|
|
|
_This is an alternative to the `CLONE_NEWPID` method; it is not currently
|
|
implemented in the Chromium codebase._
|
|
|
|
Instead of using `CLONE_NEWPID`, the `SUID` helper can use `setuid()` to put the
|
|
process into a currently-unused UID, which is allocated out of a range of UIDs.
|
|
In order to ensure that the `UID` has not been allocated for another sandbox,
|
|
the `SUID` helper uses
|
|
[getrlimit()](http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html)
|
|
to set `RLIMIT_NPROC` temporarily to a soft limit of 1. (Note that the docs
|
|
specify that [setuid()](http://www.kernel.org/doc/man-pages/online/pages/man2/setuid.2.html)
|
|
returns `EAGAIN` if `RLIMIT_NPROC` is exceeded.) We can reset `RLIMIT_NPROC`
|
|
afterwards in order to allow the sandboxed process to fork child processes.
|
|
|
|
As before, the `SUID` helper chroots the process.
|
|
|
|
As before, LinuxZygote can set itself to be undumpable to stop processes in the
|
|
sandbox from being able to `ptrace()` each other.
|
|
|
|
Limitations:
|
|
|
|
* It is not possible for an unsandboxed process to `ptrace()` a sandboxed
|
|
process because they run under different UIDs. This makes debugging harder.
|
|
There is no equivalent of the `--allow-sandbox-debugging` other than turning
|
|
the sandbox off with `--no-sandbox`.
|
|
* The `SUID` helper can check that a `UID` is unused before it uses it (hence
|
|
this is safe if the `SUID` helper is installed into multiple chroots), but
|
|
it cannot prevent other root processes from putting processes into this
|
|
`UID` after the sandbox has been started. This means we should make the
|
|
`UID` range configurable, or distributions should reserve a `UID` range.
|
|
|
|
## `CLONE_NEWNET` method
|
|
|
|
The `SUID` helper uses
|
|
[CLONE_NEWNET](http://www.kernel.org/doc/man-pages/online/pages/man2/clone.2.html)
|
|
to restrict network access.
|
|
|
|
## Future work
|
|
|
|
We are splitting the `SUID` sandbox into a separate project which will support
|
|
both the `CLONE_NEWNS` and `setuid()` methods:
|
|
http://code.google.com/p/setuid-sandbox/
|
|
|
|
Having the `SUID` helper as a separate project should make it easier for
|
|
distributions to review and package.
|
|
|
|
## Possible extensions
|
|
|
|
## History
|
|
|
|
Older versions of the sandbox helper process will _only_ run
|
|
`/opt/google/chrome/chrome`. This string is hard coded
|
|
(`sandbox/linux/suid/sandbox.cc`). If your package is going to place the
|
|
Chromium binary somewhere else you need to modify this string.
|
|
|
|
## See also
|
|
|
|
* [LinuxSUIDSandboxDevelopment](suid_sandbox_development.md)
|
|
* [LinuxSandboxing](sandboxing.md)
|
|
* General information on Chromium sandboxing:
|
|
https://dev.chromium.org/developers/design-documents/sandbox
|