Check in gVisor.
PiperOrigin-RevId: 194583126 Change-Id: Ica1d8821a90f74e7e745962d71801c598c652463
@@ -0,0 +1,7 @@
|
||||
# The sandbox filegroup is used for sandbox-internal dependencies.
|
||||
package_group(
|
||||
name = "sandbox",
|
||||
packages = [
|
||||
"//...",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,73 @@
|
||||
Want to contribute? Great! First, read this page.
|
||||
|
||||
### Before you contribute
|
||||
|
||||
Before we can use your code, you must sign the
|
||||
[Google Individual Contributor License Agreement]
|
||||
(https://cla.developers.google.com/about/google-individual)
|
||||
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
||||
copyright to your changes, even after your contribution becomes part of our
|
||||
codebase, so we need your permission to use and distribute your code. We also
|
||||
need to be sure of various other things—for instance that you'll tell us if you
|
||||
know that your code infringes on other people's patents. You don't have to sign
|
||||
the CLA until after you've submitted your code for review and a member has
|
||||
approved it, but you must do it before we can put your code into our codebase.
|
||||
Before you start working on a larger contribution, you should get in touch with
|
||||
us first through the issue tracker with your idea so that we can help out and
|
||||
possibly guide you. Coordinating up front makes it much easier to avoid
|
||||
frustration later on.
|
||||
|
||||
### Coding Guidelines
|
||||
All code should conform to the [Go style guidelines][gostyle].
|
||||
|
||||
As a secure runtime, we need to maintain the safety of all of code included in
|
||||
gVisor. The following rules help mitigate issues.
|
||||
|
||||
Definitions for the rules below:
|
||||
|
||||
`core`:
|
||||
|
||||
* `//pkg/sentry/...`
|
||||
* Transitive dependencies in `//pkg/...`
|
||||
|
||||
`runsc`:
|
||||
|
||||
* `//runsc/...`
|
||||
|
||||
Rules:
|
||||
|
||||
* No cgo in `core` or `runsc`. The final binary must be a statically-linked
|
||||
pure Go binary.
|
||||
|
||||
* Any files importing "unsafe" must have a name ending in `_unsafe.go`.
|
||||
|
||||
* `core` may only depend on the following packages:
|
||||
* Itself.
|
||||
* Go standard library.
|
||||
* Except (transitively) package "net" (this will result in a non-cgo
|
||||
binary). Use `//pkg/unet` instead.
|
||||
* `@com_golang_x_sys//unix:go_default_library` (Go import `golang.org/x/sys/unix`).
|
||||
* Generated Go protobuf packages.
|
||||
* `@com_github_golang_protobuf//proto:go_default_library` (Go import `github.com/golang/protobuf/proto`).
|
||||
* `@com_github_golang_protobuf//ptypes:go_default_library` (Go import `github.com/golang/protobuf/ptypes`).
|
||||
|
||||
* `runsc` may only depend on the following packages:
|
||||
* All packages allowed for `core`.
|
||||
* `@com_github_google_subcommands//:go_default_library` (Go import `github.com/google/subcommands`).
|
||||
* `@com_github_opencontainers_runtime_spec//specs_go:go_default_library` (Go import `github.com/opencontainers/runtime-spec/specs_go`).
|
||||
|
||||
### Code reviews
|
||||
|
||||
All changes must be submitted via [Gerrit](https://gvisor-review.googlesource.com).
|
||||
|
||||
All submissions, including submissions by project members, require review.
|
||||
Please see these [instructions](https://gvisor-review.googlesource.com/Documentation/).
|
||||
|
||||
### The small print
|
||||
|
||||
Contributions made by corporations are covered by a different agreement than
|
||||
the one above, the
|
||||
[Software Grant and Corporate Contributor License Agreement]
|
||||
(https://cla.developers.google.com/about/google-corporate).
|
||||
|
||||
[gostyle][https://github.com/golang/go/wiki/CodeReviewComments]
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,430 @@
|
||||
# gVisor
|
||||
|
||||
gVisor is a user-space kernel, written in Go, that implements a substantial
|
||||
portion of the Linux system surface. It includes an [Open Container Initiative
|
||||
(OCI)][oci] runtime called `runsc` that provides an isolation boundary between
|
||||
the application and the host kernel. The `runsc` runtime integrates with Docker
|
||||
and Kubernetes, making it simple to run sandboxed containers.
|
||||
|
||||
gVisor takes a distinct approach to container sandboxing and makes a different
|
||||
set of technical trade-offs compared to existing sandbox technologies, thus
|
||||
providing new tools and ideas for the container security landscape.
|
||||
|
||||
### Why does gVisor exist?
|
||||
|
||||
Containers are not a [**sandbox**][sandbox]. While containers have
|
||||
revolutionized how we develop, package, and deploy applications, running
|
||||
untrusted or potentially malicious code without additional isolation is not a
|
||||
good idea. The efficiency and performance gains from using a single, shared
|
||||
kernel also mean that container escape is possible with a single vulnerability.
|
||||
|
||||
gVisor is a user-space kernel for containers. It limits the host kernel surface
|
||||
accessible to the application while still giving the application access to all
|
||||
the features it expects. Unlike most kernels, gVisor does not assume or require
|
||||
a fixed set of physical resources; instead, it leverages existing host kernel
|
||||
functionality and runs as a normal user-space process. In other words, gVisor
|
||||
implements Linux by way of Linux.
|
||||
|
||||
gVisor should not be confused with technologies and tools to harden containers
|
||||
against external threats, provide additional integrity checks, or limit the
|
||||
scope of access for a service. One should always be careful about what data is
|
||||
made available to a container.
|
||||
|
||||
### How is gVisor different from other container isolation mechanisms?
|
||||
|
||||
Two other approaches are commonly taken to provide stronger isolation than
|
||||
native containers.
|
||||
|
||||

|
||||
|
||||
**Machine-level virtualization**, such as [KVM][kvm] and [Xen][xen], exposes
|
||||
virtualized hardware to a guest kernel via a Virtual Machine Monitor (VMM). This
|
||||
virtualized hardware is generally enlightened (paravirtualized) and additional
|
||||
mechanisms can be used to improve the visibility between the guest and host
|
||||
(e.g. balloon drivers, paravirtualized spinlocks). Running containers in
|
||||
distinct virtual machines can provide great isolation, compatibility and
|
||||
performance (though nested virtualization may bring challenges in this area),
|
||||
but for containers it often requires additional proxies and agents, and may
|
||||
require a larger resource footprint and slower start-up times.
|
||||
|
||||

|
||||
|
||||
**Rule-based execution**, such as [seccomp][seccomp], [SELinux][selinux] and
|
||||
[AppArmor][apparmor], allows the specification of a fine-grained security policy
|
||||
for an application or container. These schemes typically rely on hooks
|
||||
implemented inside the host kernel to enforce the rules. If the surface can be
|
||||
made small enough (i.e. a sufficiently complete policy defined), then this is
|
||||
an excellent way to sandbox applications and maintain native performance.
|
||||
However, in practice it can be extremely difficult (if not impossible) to
|
||||
reliably define a policy for arbitrary, previously unknown applications,
|
||||
making this approach challenging to apply universally.
|
||||
|
||||
Rule-based execution is often combined with additional layers for
|
||||
defense-in-depth.
|
||||
|
||||

|
||||
|
||||
**gVisor** provides a third isolation mechanism, distinct from those mentioned
|
||||
above.
|
||||
|
||||
gVisor intercepts application system calls and acts as the guest kernel, without
|
||||
the need for translation through virtualized hardware. gVisor may be thought of
|
||||
as either a merged guest kernel and VMM, or as seccomp on steroids. This
|
||||
architecture allows it to provide a flexible resource footprint (i.e. one based
|
||||
on threads and memory mappings, not fixed guest physical resources) while also
|
||||
lowering the fixed costs of virtualization. However, this comes at the price of
|
||||
reduced application compatibility and higher per-system call overhead.
|
||||
|
||||
On top of this, gVisor employs rule-based execution to provide defense-in-depth
|
||||
(details below).
|
||||
|
||||
gVisor's approach is similar to [User Mode Linux (UML)][uml], although UML
|
||||
virtualizes hardware internally and thus provides a fixed resource footprint.
|
||||
|
||||
Each of the above approaches may excel in distinct scenarios. For example,
|
||||
machine-level virtualization will face challenges achieving high density, while
|
||||
gVisor may provide poor performance for system call heavy workloads.
|
||||
|
||||
### Why Go?
|
||||
|
||||
gVisor was written in Go in order to avoid security pitfalls that can plague
|
||||
kernels. With Go, there are strong types, built-in bounds checks, no
|
||||
uninitialized variables, no use-after-free, no stack overflow, and a built-in
|
||||
race detector. (The use of Go has its challenges too, and isn't free.)
|
||||
|
||||
## Architecture
|
||||
|
||||
gVisor intercepts all system calls made by the application, and does the
|
||||
necessary work to service them. Importantly, gVisor does not simply redirect
|
||||
application system calls through to the host kernel. Instead, gVisor implements
|
||||
most kernel primitives (signals, file systems, futexes, pipes, mm, etc.) and has
|
||||
complete system call handlers built on top of these primitives.
|
||||
|
||||
Since gVisor is itself a user-space application, it will make some host system
|
||||
calls to support its operation, but much like a VMM, it will not allow the
|
||||
application to directly control the system calls it makes.
|
||||
|
||||
### File System Access
|
||||
|
||||

|
||||
|
||||
In order to provide defense-in-depth and limit the host system surface, the
|
||||
gVisor container runtime is normally split into two separate processes. First,
|
||||
the *Sentry* process includes the kernel and is responsible for executing user
|
||||
code and handling system calls. Second, file system operations that extend beyond
|
||||
the sandbox (not internal proc or tmp files, pipes, etc.) are sent to a proxy,
|
||||
called a *Gofer*, via a 9P connection.
|
||||
|
||||
The Gofer acts as a file system proxy by opening host files on behalf of the
|
||||
application, and passing them to the Sentry process, which has no host file
|
||||
access itself. Furthermore, the Sentry runs in an empty user namespace, and the
|
||||
system calls made by gVisor to the host are restricted using seccomp filters in
|
||||
order to provide defense-in-depth.
|
||||
|
||||
### Network Access
|
||||
|
||||
The Sentry implements its own network stack (also written in Go) called
|
||||
[netstack][netstack]. All aspects of the network stack are handled inside the
|
||||
Sentry — including TCP connection state, control messages, and packet assembly —
|
||||
keeping it isolated from the host network stack. Data link layer packets are
|
||||
written directly to the virtual device inside the network namespace setup by
|
||||
Docker or Kubernetes.
|
||||
|
||||
A network passthrough mode is also supported, but comes at the cost of reduced
|
||||
isolation (see below).
|
||||
|
||||
### Platforms
|
||||
|
||||
The Sentry requires a *platform* to implement basic context switching and memory
|
||||
mapping functionality. Today, gVisor supports two platforms:
|
||||
|
||||
* The **Ptrace** platform uses SYSEMU functionality to execute user code without
|
||||
executing host system calls. This platform can run anywhere that `ptrace`
|
||||
works (even VMs without nested virtualization).
|
||||
|
||||
* The **KVM** platform allows the Sentry to act as both guest OS and VMM,
|
||||
switching back and forth between the two worlds seamlessly. The KVM platform
|
||||
can run on bare-metal or on a VM with nested virtualization enabled. While
|
||||
there is no virtualized hardware layer -- the sandbox retains a process model
|
||||
-- gVisor leverages virtualization extensions available on modern processors
|
||||
in order to improve isolation and performance of address space switches.
|
||||
|
||||
### Performance
|
||||
|
||||
There are several factors influencing performance. The platform choice has the
|
||||
largest direct impact that varies depending on the specific workload. There is
|
||||
no best platform: Ptrace works universally, including on VM instances, but
|
||||
applications may perform at a fraction of their original levels. Beyond the
|
||||
platform choice, passthrough modes may be useful for improving perfomance at the
|
||||
cost of some isolation.
|
||||
|
||||
## Installation
|
||||
|
||||
These instructions will get you up-and-running sandboxed containers with gVisor
|
||||
and Docker.
|
||||
|
||||
### Requirements
|
||||
|
||||
* [git][git]
|
||||
* [Bazel][bazel]
|
||||
* [Docker version 17.09.0 or greater][docker]
|
||||
|
||||
### Getting the source
|
||||
|
||||
Clone the gVisor repo:
|
||||
|
||||
```
|
||||
git clone https://gvisor.googlesource.com/gvisor gvisor
|
||||
cd gvisor
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
Build and install the `runsc` binary.
|
||||
|
||||
It is important to copy this binary to some place that is accessible to all
|
||||
users, since `runsc` executes itself as user `nobody` to avoid unnecessary
|
||||
privileges. The `/usr/local/bin` directory is a good choice.
|
||||
|
||||
```
|
||||
bazel build runsc
|
||||
sudo cp ./bazel-bin/runsc/linux_amd64_pure_stripped/runsc /usr/local/bin
|
||||
```
|
||||
|
||||
### Configuring Docker
|
||||
|
||||
Next, configure Docker to use `runsc` by adding a runtime entry to your Docker
|
||||
configuration (`/etc/docker/daemon.json`). You may have to create this file if
|
||||
it does not exist. Also, some Docker versions also require you to [specify the
|
||||
`storage-driver` field][docker-storage-driver].
|
||||
|
||||
In the end, the file should look something like:
|
||||
|
||||
```
|
||||
{
|
||||
"runtimes": {
|
||||
"runsc": {
|
||||
"path": "/usr/local/bin/runsc"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You must restart the Docker daemon after making changes to this file, typically this is done via:
|
||||
|
||||
```
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
Now run your container in `runsc`:
|
||||
|
||||
```
|
||||
docker run --runtime=runsc hello-world
|
||||
```
|
||||
|
||||
Terminal support works too:
|
||||
|
||||
```
|
||||
docker run --runtime=runsc -it ubuntu /bin/bash
|
||||
```
|
||||
|
||||
|
||||
### Kubernetes Support (Experimental)
|
||||
|
||||
gVisor can run sandboxed containers in a Kubernetes cluster with cri-o, although
|
||||
this is not recommended for production environments yet. Follow [these
|
||||
instructions][cri-o-k8s] to run [cri-o][cri-o] on a node in a Kubernetes
|
||||
cluster. Build `runsc` and put it on the node, and set it as the
|
||||
`runtime_untrusted_workload` in `/etc/crio/crio.conf`.
|
||||
|
||||
Any Pod without the `io.kubernetes.cri-o.TrustedSandbox` annotation (or with the
|
||||
annotation set to false) will be run with `runsc`.
|
||||
|
||||
Currently, gVisor only supports Pods with a single container (not counting the
|
||||
ever-present pause container). Support for multiple containers within a single
|
||||
Pod is coming soon.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Testing
|
||||
|
||||
The gVisor test suite can be run with Bazel:
|
||||
|
||||
```
|
||||
bazel test ...
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
To enable debug + system call logging, add the `runtimeArgs` below to your
|
||||
Docker configuration (`/etc/docker/daemon.json`):
|
||||
|
||||
```
|
||||
{
|
||||
"runtimes": {
|
||||
"runsc": {
|
||||
"path": "/usr/local/bin/runsc"
|
||||
"runtimeArgs": [
|
||||
"--debug-log-dir=/tmp/runsc",
|
||||
"--debug",
|
||||
"--strace"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You may also want to pass `--log-packets` to troubleshoot network problems. Then
|
||||
restart the Docker daemon:
|
||||
|
||||
```
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
Run your container again, and inspect the files under `/tmp/runsc`. The log file
|
||||
with name `boot` will contain the strace logs from your application, which can
|
||||
be useful for identifying missing or broken system calls in gVisor.
|
||||
|
||||
### Enabling network passthrough
|
||||
|
||||
For high-performance networking applications, you may choose to disable the user
|
||||
space network stack and instead use the host network stack. Note that this mode
|
||||
decreases the isolation to the host.
|
||||
|
||||
Add the following `runtimeArgs` to your Docker configuration
|
||||
(`/etc/docker/daemon.json`) and restart the Docker daemon:
|
||||
|
||||
```
|
||||
{
|
||||
"runtimes": {
|
||||
"runsc": {
|
||||
"path": "/usr/local/bin/runsc"
|
||||
"runtimeArgs": [
|
||||
"--network=host"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Selecting a different platform
|
||||
|
||||
Depending on hardware and performance characteristics, you may choose to use a
|
||||
different platform. The Ptrace platform is the default, but the KVM platform may
|
||||
be specified by passing the `--platform` flag to `runsc` in your Docker
|
||||
configuration (`/etc/docker/daemon.json`):
|
||||
|
||||
```
|
||||
{
|
||||
"runtimes": {
|
||||
"runsc": {
|
||||
"path": "/usr/local/bin/runsc"
|
||||
"runtimeArgs": [
|
||||
"--platform=kvm"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then restart the Docker daemon.
|
||||
|
||||
## FAQ & Known Issues
|
||||
|
||||
### What works?
|
||||
|
||||
The following applications/images have been tested:
|
||||
|
||||
* golang
|
||||
* httpd
|
||||
* java8
|
||||
* jenkins
|
||||
* mariadb
|
||||
* memcached
|
||||
* mongo
|
||||
* mysql
|
||||
* node
|
||||
* php
|
||||
* prometheus
|
||||
* python
|
||||
* redis
|
||||
* registry
|
||||
* tomcat
|
||||
* wordpress
|
||||
|
||||
### What doesn't work yet?
|
||||
|
||||
The following applications have been tested and may not yet work:
|
||||
|
||||
* elasticsearch: Requires unimplemented socket ioctls. See [bug
|
||||
#2](https://github.com/google/gvisor/issues/2).
|
||||
* nginx: Requires `ioctl(FIOASYNC)`, but see workaround in [bug
|
||||
#1](https://github.com/google/gvisor/issues/1).
|
||||
* postgres: Requires SysV shared memory support. See [bug
|
||||
#3](https://github.com/google/gvisor/issues/3).
|
||||
|
||||
### Will my container work with gVisor?
|
||||
|
||||
gVisor implements a large portion of the Linux surface and while we strive to
|
||||
make it broadly compatible, there are (and always will be) unimplemented
|
||||
features and bugs. The only real way to know if it will work is to try. If you
|
||||
find a container that doesn’t work and there is no known issue, please [file a
|
||||
bug][bug] indicating the full command you used to run the image. Providing the
|
||||
debug logs is also helpful.
|
||||
|
||||
### My container runs fine with *runc* but fails with *runsc*.
|
||||
|
||||
If you’re having problems running a container with `runsc` it’s most likely due
|
||||
to a compatibility issue or a missing feature in gVisor. See **Debugging**,
|
||||
above.
|
||||
|
||||
### I can’t see a file copied with `docker cp` or `kubectl cp`.
|
||||
|
||||
For performance reasons, gVisor caches directory contents, and therefore it may
|
||||
not realize a new file was copied to a given directory. To invalidate the cache
|
||||
and force a refresh, create a file under the directory in question and list the
|
||||
contents again.
|
||||
|
||||
This bug is tracked in [bug #4](https://github.com/google/gvisor/issues/4).
|
||||
|
||||
## Technical details
|
||||
|
||||
We plan to release a full paper with technical details and will include it
|
||||
here when available.
|
||||
|
||||
## Community
|
||||
|
||||
Join the [gvisor-discuss mailing list][gvisor-discuss-list] to discuss all things
|
||||
gVisor.
|
||||
|
||||
Sensitive security-related questions and comments can be sent to the private
|
||||
[gvisor-security mailing list][gvisor-security-list].
|
||||
|
||||
## Contributing
|
||||
|
||||
See [Contributing.md](CONTRIBUTING.md).
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This is not an official Google product (experimental or otherwise), it is just
|
||||
code that happens to be owned by Google.
|
||||
|
||||
[apparmor]: https://wiki.ubuntu.com/AppArmor
|
||||
[bazel]: https://bazel.build
|
||||
[bug]: https://github.com/google/gvisor/issues
|
||||
[cri-o]: https://github.com/kubernetes-incubator/cri-o
|
||||
[cri-o-k8s]: https://github.com/kubernetes-incubator/cri-o/blob/master/kubernetes.md
|
||||
[docker]: https://www.docker.com
|
||||
[docker-storage-driver]: https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-storage-driver
|
||||
[git]: https://git-scm.com
|
||||
[gvisor-discuss-list]: https://groups.google.com/forum/#!forum/gvisor-users
|
||||
[gvisor-security-list]: https://groups.google.com/forum/#!forum/gvisor-security
|
||||
[kvm]: https://www.linux-kvm.org
|
||||
[netstack]: https://github.com/google/netstack
|
||||
[oci]: https://www.opencontainers.org
|
||||
[sandbox]: https://en.wikipedia.org/wiki/Sandbox_(computer_security)
|
||||
[seccomp]: https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
|
||||
[selinux]: https://selinuxproject.org
|
||||
[uml]: http://user-mode-linux.sourceforge.net/
|
||||
[xen]: https://www.xenproject.org
|
||||
@@ -0,0 +1,72 @@
|
||||
# Depend on the go bazel rules.
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
url = "https://github.com/bazelbuild/rules_go/releases/download/0.11.0/rules_go-0.11.0.tar.gz",
|
||||
sha256 = "f70c35a8c779bb92f7521ecb5a1c6604e9c3edd431e50b6376d7497abc8ad3c1",
|
||||
)
|
||||
|
||||
# Load go bazel rules and toolchain.
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_repository", "go_rules_dependencies", "go_register_toolchains")
|
||||
go_rules_dependencies()
|
||||
go_register_toolchains(go_version="1.10.1")
|
||||
|
||||
# Add dependencies on external repositories.
|
||||
go_repository(
|
||||
name = "com_github_google_go-cmp",
|
||||
importpath = "github.com/google/go-cmp",
|
||||
commit = "3af367b6b30c263d47e8895973edcca9a49cf029",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_google_subcommands",
|
||||
importpath = "github.com/google/subcommands",
|
||||
commit = "ce3d4cfc062faac7115d44e5befec8b5a08c3faa",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_google_uuid",
|
||||
importpath = "github.com/google/uuid",
|
||||
commit = "dec09d789f3dba190787f8b4454c7d3c936fed9e",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_kr_pty",
|
||||
importpath = "github.com/kr/pty",
|
||||
commit = "282ce0e5322c82529687d609ee670fac7c7d917c",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_opencontainers_runtime-spec",
|
||||
importpath = "github.com/opencontainers/runtime-spec",
|
||||
commit = "b2d941ef6a780da2d9982c1fb28d77ad97f54fc7",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_vishvananda_netlink",
|
||||
importpath = "github.com/vishvananda/netlink",
|
||||
commit = "d35d6b58e1cb692b27b94fc403170bf44058ac3e",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_vishvananda_netns",
|
||||
importpath = "github.com/vishvananda/netns",
|
||||
commit = "be1fbeda19366dea804f00efff2dd73a1642fdcc",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_net",
|
||||
importpath = "golang.org/x/net",
|
||||
commit = "b3c676e531a6dc479fa1b35ac961c13f5e2b4d2e",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_sys",
|
||||
importpath = "golang.org/x/sys",
|
||||
commit = "0dd5e194bbf5eb84a39666eb4c98a4d007e4203a",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_syndtr_gocapability",
|
||||
importpath = "github.com/syndtr/gocapability",
|
||||
commit = "33e07d32887e1e06b7c025f27ce52f62c7990bc0",
|
||||
)
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 79 KiB |
@@ -0,0 +1,11 @@
|
||||
# Location of bash script that runs the test. The first directory in the path
|
||||
# is the directory where Kokoro will check out the repo. The rest is the path
|
||||
# is the path to the test script.
|
||||
build_file: "repo/kokoro/gcp_ubuntu/run_tests.sh"
|
||||
|
||||
action {
|
||||
define_artifacts {
|
||||
regex: "**/sponge_log.xml"
|
||||
regex: "**/test.log"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Location of bash script that runs the test. The first directory in the path
|
||||
# is the directory where Kokoro will check out the repo. The rest is the path
|
||||
# is the path to the test script.
|
||||
build_file: "repo/kokoro/gcp_ubuntu/run_tests.sh"
|
||||
|
||||
action {
|
||||
define_artifacts {
|
||||
regex: "**/sponge_log.xml"
|
||||
regex: "**/test.log"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2018 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Fail on any error.
|
||||
set -e
|
||||
# Display commands to stderr.
|
||||
set -x
|
||||
|
||||
# Install the latest version of Bazel.
|
||||
use_bazel.sh latest
|
||||
|
||||
# Log the bazel path and version.
|
||||
which bazel
|
||||
bazel version
|
||||
|
||||
cd git/repo
|
||||
|
||||
# Build everything.
|
||||
bazel build //...
|
||||
|
||||
# Run the tests and upload results.
|
||||
#
|
||||
# We turn off "-e" flag because we must move the log files even if the test
|
||||
# fails.
|
||||
set +e
|
||||
bazel test --test_output=errors //...
|
||||
exit_code=${?}
|
||||
set -e
|
||||
|
||||
# Find and rename all test logs so that Sponge can pick them up.
|
||||
for file in $(find -L "bazel-testlogs" -name "test.xml"); do
|
||||
newpath=${KOKORO_ARTIFACTS_DIR}/$(dirname ${file})
|
||||
# XML logs must be named sponge_log.xml for sponge to process them.
|
||||
mkdir -p "${newpath}" && cp "${file}" "${newpath}/sponge_log.xml"
|
||||
done
|
||||
for file in $(find -L "bazel-testlogs" -name "test.log"); do
|
||||
newpath=${KOKORO_ARTIFACTS_DIR}/$(dirname ${file})
|
||||
mkdir -p "${newpath}" && cp "${file}" "${newpath}"
|
||||
done
|
||||
|
||||
exit ${exit_code}
|
||||
@@ -0,0 +1,25 @@
|
||||
package(licenses = ["notice"]) # Apache 2.0
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
load("//tools/go_stateify:defs.bzl", "go_stateify")
|
||||
|
||||
go_stateify(
|
||||
name = "abi_state",
|
||||
srcs = [
|
||||
"abi.go",
|
||||
],
|
||||
out = "abi_state.go",
|
||||
package = "abi",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "abi",
|
||||
srcs = [
|
||||
"abi.go",
|
||||
"abi_state.go",
|
||||
"flag.go",
|
||||
],
|
||||
importpath = "gvisor.googlesource.com/gvisor/pkg/abi",
|
||||
visibility = ["//:sandbox"],
|
||||
deps = ["//pkg/state"],
|
||||
)
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2018 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package abi describes the interface between a kernel and userspace.
|
||||
package abi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// OS describes the target operating system for an ABI.
|
||||
//
|
||||
// Note that OS is architecture-independent. The details of the OS ABI will
|
||||
// vary between architectures.
|
||||
type OS int
|
||||
|
||||
const (
|
||||
// Linux is the Linux ABI.
|
||||
Linux OS = iota
|
||||
)
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (o OS) String() string {
|
||||
switch o {
|
||||
case Linux:
|
||||
return "linux"
|
||||
default:
|
||||
return fmt.Sprintf("OS(%d)", o)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2018 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package abi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A FlagSet is a slice of bit-flags and their name.
|
||||
type FlagSet []struct {
|
||||
Flag uint64
|
||||
Name string
|
||||
}
|
||||
|
||||
// Parse returns a pretty version of val, using the flag names for known flags.
|
||||
// Unknown flags remain numeric.
|
||||
func (s FlagSet) Parse(val uint64) string {
|
||||
var flags []string
|
||||
|
||||
for _, f := range s {
|
||||
if val&f.Flag == f.Flag {
|
||||
flags = append(flags, f.Name)
|
||||
val &^= f.Flag
|
||||
}
|
||||
}
|
||||
|
||||
if val != 0 {
|
||||
flags = append(flags, "0x"+strconv.FormatUint(val, 16))
|
||||
}
|
||||
|
||||
return strings.Join(flags, "|")
|
||||
}
|
||||
|
||||
// ValueSet is a slice of syscall values and their name. Parse will replace
|
||||
// values that exactly match an entry with its name.
|
||||
type ValueSet []struct {
|
||||
Value uint64
|
||||
Name string
|
||||
}
|
||||
|
||||
// Parse returns the name of the value associated with `val`. Unknown values
|
||||
// are converted to hex.
|
||||
func (e ValueSet) Parse(val uint64) string {
|
||||
for _, f := range e {
|
||||
if val == f.Value {
|
||||
return f.Name
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%#x", val)
|
||||
}
|
||||
|
||||
// ParseName returns the flag value associated with 'name'. Returns false
|
||||
// if no value is found.
|
||||
func (e ValueSet) ParseName(name string) (uint64, bool) {
|
||||
for _, f := range e {
|
||||
if name == f.Name {
|
||||
return f.Value, true
|
||||
}
|
||||
}
|
||||
return math.MaxUint64, false
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
# Package linux contains the constants and types needed to inferface with a
|
||||
# Linux kernel. It should be used instead of syscall or golang.org/x/sys/unix
|
||||
# when the host OS may not be Linux.
|
||||
|
||||
package(licenses = ["notice"]) # Apache 2.0
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
load("//tools/go_stateify:defs.bzl", "go_stateify")
|
||||
|
||||
go_stateify(
|
||||
name = "linux_state",
|
||||
srcs = [
|
||||
"binder.go",
|
||||
"bpf.go",
|
||||
"time.go",
|
||||
"tty.go",
|
||||
],
|
||||
out = "linux_state.go",
|
||||
package = "linux",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "linux",
|
||||
srcs = [
|
||||
"aio.go",
|
||||
"ashmem.go",
|
||||
"binder.go",
|
||||
"bpf.go",
|
||||
"capability.go",
|
||||
"dev.go",
|
||||
"elf.go",
|
||||
"errors.go",
|
||||
"exec.go",
|
||||
"file.go",
|
||||
"fs.go",
|
||||
"futex.go",
|
||||
"inotify.go",
|
||||
"ioctl.go",
|
||||
"ip.go",
|
||||
"ipc.go",
|
||||
"limits.go",
|
||||
"linux.go",
|
||||
"linux_state.go",
|
||||
"mm.go",
|
||||
"netdevice.go",
|
||||
"netlink.go",
|
||||
"netlink_route.go",
|
||||
"poll.go",
|
||||
"prctl.go",
|
||||
"rusage.go",
|
||||
"sched.go",
|
||||
"seccomp.go",
|
||||
"sem.go",
|
||||
"signal.go",
|
||||
"socket.go",
|
||||
"time.go",
|
||||
"tty.go",
|
||||
"uio.go",
|
||||
"utsname.go",
|
||||
],
|
||||
importpath = "gvisor.googlesource.com/gvisor/pkg/abi/linux",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/abi",
|
||||
"//pkg/binary",
|
||||
"//pkg/bits",
|
||||
"//pkg/state",
|
||||
],
|
||||
)
|
||||