# Technical Documentation: opencontainers/runc

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/opencontainers/runc)

### Overview (`README.md`)

# runc

[](https://pkg.go.dev/github.com/opencontainers/runc)
[](https://bestpractices.coreinfrastructure.org/projects/588)
[](https://github.com/opencontainers/runc/actions?query=workflow%3Avalidate)
[](https://github.com/opencontainers/runc/actions?query=workflow%3Aci)

## Introduction

`runc` is a CLI tool for spawning and running containers on Linux according to the OCI specification.

## Releases

You can find official releases of `runc` on the [release](https://github.com/opencontainers/runc/releases) page.

All releases are signed by one of the keys listed in the [`runc.keyring` file in the root of this repository](runc.keyring).

## Security

The reporting process and disclosure communications are outlined [here](https://github.com/opencontainers/org/blob/main/SECURITY.md).

### Security Audit
A third party security audit was performed by Cure53, you can see the full report [here](https://github.com/opencontainers/runc/blob/main/docs/Security-Audit.pdf).

## Building

`runc` only supports Linux. See the header of [`go.mod`](./go.mod) for the minimally required Go version.

### Pre-Requisites

#### Utilities and Libraries

In addition to Go, building `runc` requires multiple utilities and libraries to be installed on your system.

On Ubuntu/Debian, you can install the required dependencies with:

```bash
apt update && apt install -y make gcc linux-libc-dev libseccomp-dev pkg-config git
```

On CentOS/Fedora, you can install the required dependencies with:

```bash
yum install -y make gcc kernel-headers libseccomp-devel pkg-config git
```

On Alpine Linux, you can install the required dependencies with:

```bash
apk --update add bash make gcc libseccomp-dev musl-dev linux-headers git
```

The following dependencies are optional:

* `libseccomp` - only required if you enable seccomp support; to disable, see [Build Tags](#build-tags).
* `libpathrs` - only required if you enable libpathrs support; to disable, see [Build Tags](#build-tags).
   For notes on installing libpathrs, see [the next section](#libpathrs).

##### libpathrs

[libpathrs][] is a Rust library runc can optionally use for path safety. As
mentioned in [the build tag section](#build-tags), its use is controlled with
the `libpathrs` build tag. runc currently requires *at least libpathrs 0.2.5*
in order to function properly.

At time of writing, very few distributions have libpathrs packages and so it is
usually necessary to build and install it locally. For detailed installation
instructions, see [the upstream documentation][libpathrs-install-md], but for
development builds the following instructions should be sufficient:

libpathrs requires Rust 1.63+ (which is available on almost any distribution,
including Debian oldstable and enterprise distributions like RHEL or SLES).
Assuming you already have `cargo` installed (as well as other libpathrs
dependencies like `clang` and `lld`), the following steps are all that are
really necessary to install libpathrs:

```sh
LIBPATHRS_VERSION=0.2.5
curl -o - -sSL https://github.com/cyphar/libpathrs/releases/download/v${LIBPATHRS_VERSION}/libpathrs-${LIBPATHRS_VERSION}.tar.xz | tar xvfJ -
cd libpathrs-${LIBPATHRS_VERSION}/
make release
sudo ./install.sh --prefix=/usr/local
sudo ldconfig
```

As part of our CI, we make use of a custom [installation script for
libpathrs][libpathrs-install-script] which may be useful as a reference for
folks with more complicated needs. With `script/build-libpathrs.sh` the
installation of libpathrs becomes as simple as:

```sh
sudo ./script/build-libpathrs.sh "$LIBPATHRS_VERSION" /usr/local
sudo ldconfig
```

However, please note that this installation script is **completely
unsupported** and is not really intended for general use (it includes some
workarounds for issues in our CI which will no longer be necessary once
libpathrs has distribution packages we can use).

[libpathrs]: https://github.com/cyphar/libpathrs
[libpathrs-install-md]: https://github.com/cyphar/libpathrs/blob/main/INSTALL.md
[libpathrs-install-script]: ./script/build-libpathrs.sh
[gha-test-yml]: ./.github/workflows/test.yml

### Build

```bash
# create a 'github.com/opencontainers' in your GOPATH/src
cd github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc

make
sudo make install
```

You can also use `go get` to install to your `GOPATH`, assuming that you have a `github.com` parent folder already created under `src`:

```bash
go get github.com/opencontainers/runc
cd $GOPATH/src/github.com/opencontainers/runc
make
sudo make install
```

`runc` will be installed to `/usr/local/sbin/runc` on your system.

#### Version string customization

You can see the runc version by running `runc --version`. You can append a custom string to the
version using the `EXTRA_VERSION` make variable when building, e.g.:

```bash
make EXTRA_VERSION="+build-1"
```

Bear in mind to include some separator for readability.

#### Build Tags

`runc` supports optional build tags for compiling support of various features,
with some of them enabled by default in the top-level Makefile.

The following build tags are currently recognized:

| Build Tag     | Feature                               | Set by Default | Dependencies        |
|---------------|---------------------------------------|----------------|---------------------|
| `seccomp`     | Syscall filtering using `libseccomp`. | yes            | `libseccomp`        |
| `libpathrs`   | Use [`libpathrs`][] for path safety.  | yes            | [`libpathrs`][]     |
| `runc_nocriu` | **Disables** runc checkpoint/restore. | no             | `criu`              |

[`libpathrs`]: https://github.com/cyphar/libpathrs

To add or remove build tags from the default set, use the `RUNC_BUILDTAGS`
make or shell variable. Tags prefixed with `-` are removed from the default set;
others are added. For example:

```bash
# Add runc_nocriu and remove seccomp tag.
make RUNC_BUILDTAGS="runc_nocriu -seccomp"
```

The following build tags were used earlier, but are now obsoleted:
 - **runc_nodmz** (since runc v1.2.1 runc dmz binary is dropped)
 - **nokmem** (since runc v1.0.0-rc94 kernel memory settings are ignored)
 - **apparmor** (since runc v1.0.0-rc93 the feature is always enabled)
 - **selinux**  (since runc v1.0.0-rc93 the feature is always enabled)

### Running the test suite

`runc` currently supports running its test suite via Docker.
To run the suite just type `make test`.

```bash
make test
```

There are additional make targets for running the tests outside of a container but this is not recommended as the tests are written with the expectation that they can write and remove anywhere.

You can run a specific test case by setting the `TESTFLAGS` variable.

```bash
# make test TESTFLAGS="-run=SomeTestFunction"
```

You can run a specific integration test by setting the `TESTPATH` variable.

```bash
# make test TESTPATH="/checkpoint.bats"
```

You can run a specific rootless integration test by setting the `ROOTLESS_TESTPATH` variable.

```bash
# make test ROOTLESS_TESTPATH="/checkpoint.bats"
```

You can run a test using your container engine's flags by setting `CONTAINER_ENGINE_BUILD_FLAGS` and `CONTAINER_ENGINE_RUN_FLAGS` variables.

```bash
# make test CONTAINER_ENGINE_BUILD_FLAGS="--build-arg http_proxy=http://yourproxy/" CONTAINER_ENGINE_RUN_FLAGS="-e http_proxy=http://yourproxy/"
```

### Go Dependencies Management

`runc` uses [Go Modules](https://github.com/golang/go/wiki/Modules) for dependencies management.
Please refer to [Go Modules](https://github.com/golang/go/wiki/Modules) for how to add or update
new dependencies.

```
# Update vendored dependencies
make vendor
# Verify all dependencies
make verify-dependencies
```

## Using runc

Please note that runc is a low level tool not designed with an end user
in mind. It is mostly employed by other higher level container software.

Therefore, unless there is some specific use case that prevents the use
of tools like Docker or Podman, it is not recommended to use runc directly.

If you still want to use runc, here's how.

### Creating an OCI Bundle

In order to use runc you must have your container in the format of an OCI bundle.
If you have Docker installed you can use its `export` method to acquire a root filesystem from an existing Docker container.

```bash
# create the top most bundle directory
mkdir /mycontainer
cd /mycontainer

# create the rootfs directory
mkdir rootfs

# export busybox via Docker into the rootfs directory
docker export $(docker create busybox) | tar -C rootfs -xvf -
```

After a root filesystem is populated you just generate a spec in the format of a `config.json` file inside your bundle.
`runc` provides a `spec` command to generate a base template spec that you are then able to edit.
To find features and documentation for fields in the spec please refer to the [specs](https://github.com/opencontainers/runtime-spec) repository.

```bash
runc spec
```

### Running Containers

Assuming you have an OCI bundle from the previous step you can execute the container in two different ways.

The first way is to use the convenience command `run` that will handle creating, starting, and deleting the container after it exits.

```bash
# run as root
cd /mycontainer
runc run mycontainerid
```

If you used the unmodified `runc spec` template this should give you a `sh` session inside the container.

The second way to start a container is using the specs lifecycle operations.
This gives you more power over how the container is created and managed while it is running.
This will also launch the container in the background so you will have to edit
the `config.json` to remove the `terminal` setting for the simple examples
below (see more details about [runc terminal handling](docs/terminals.md)).
Your process field in the `config.json` should look like this below with `"terminal": false` and `"args": ["sleep", "5"]`.


```
/* Detailed source-code truncated for AI context efficiency. */
```

Now we can go through the lifecycle operations in your shell.


```bash
# run as root
cd /mycontainer
runc create mycontainerid

# view the container is created and in the "created" state
runc list

# start the process inside the container
runc start mycontainerid

# after 5 seconds view that the container has exited and is now in the stopped state
runc list

# now delete the container
runc delete mycontainerid
```

This allows higher level systems to augment the containers creation logic with setup of various settings after the container is created and/or before it is deleted. For example, the container's network stack is commonly set up after `create` but before `start`.

#### Rootless containers
`runc` has the ability to run containers without root privileges. This is called `rootless`. You need to pass some parameters to `runc` in order to run rootless containers. See below and compare with the previous version.

**Note:** In order to use this feature, "User Namespaces" must be compiled and enabled in your kernel. There are various ways to do this depending on your distribution:
- Confirm `CONFIG_USER_NS=y` is set in your kernel configuration (normally found in `/proc/config.gz`)
- Arch/Debian: `echo 1 > /proc/sys/kernel/unprivileged_userns_clone`
- RHEL/CentOS 7: `echo 28633 > /proc/sys/user/max_user_namespaces`

Run the following commands as an ordinary user:
```bash
# Same as the first example
mkdir ~/mycontainer
cd ~/mycontainer
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -

# The --rootless parameter instructs runc spec to generate a configuration for a rootless container, which will allow you to run the container as a non-root user.
runc spec --rootless

# The --root parameter tells runc where to store the container state. It must be writable by the user.
runc --root /tmp/runc run mycontainerid
```

#### Supervisors

`runc` can be used with process supervisors and init systems to ensure that containers are restarted when they exit.
An example systemd unit file looks something like this.

```systemd
[Unit]
Description=Start My Container

[Service]
Type=forking
ExecStart=/usr/local/sbin/runc run -d --pid-file /run/mycontainerid.pid mycontainerid
ExecStopPost=/usr/local/sbin/runc delete mycontainerid
WorkingDirectory=/mycontainer
PIDFile=/run/mycontainerid.pid

[Install]
WantedBy=multi-user.target
```

## More documentation

* [Spec conformance](./docs/spec-conformance.md)
* [cgroup v2](./docs/cgroup-v2.md)
* [Checkpoint and restore](./docs/checkpoint-restore.md)
* [systemd cgroup driver](./docs/systemd.md)
* [Terminals and standard IO](./docs/terminals.md)
* [Experimental features](./docs/experimental.md)
* [Deprecated features](./docs/deprecated.md)

## License

The code and docs are released under the [Apache 2.0 license](LICENSE).

---

### Overview (`libcontainer/README.md`)

# libcontainer

[](https://pkg.go.dev/github.com/opencontainers/runc/libcontainer)

Libcontainer provides a native Go implementation for creating containers
with namespaces, cgroups, capabilities, and filesystem access controls.
It allows you to manage the lifecycle of the container performing additional operations
after the container is created.


## Container
A container is a self contained execution environment that shares the kernel of the
host system and which is (optionally) isolated from other containers in the system.

## Using libcontainer

For a brief overview of using libcontainer, see [example_test.go](example_test.go).

### Container init

Because containers are spawned in a two step process you will need a binary that
will be executed as the init process for the container. In libcontainer, we use
the current binary (/proc/self/exe) to be executed as the init process, and use
arg "init", we call the first step process "bootstrap", so you always need a "init"
function as the entry of "bootstrap".

In addition to the go init function the early stage bootstrap is handled by importing
[nsenter](../nsenter/README.md).

For details on how runc implements such "init", see
[../init.go](../init.go) and [init_linux.go](init_linux.go).

## Checkpoint & Restore

libcontainer now integrates [CRIU](http://criu.org/) for checkpointing and restoring containers.
This lets you save the state of a process running inside a container to disk, and then restore
that state into a new process, on the same machine or on another machine.

`criu` version 1.5.2 or higher is required to use checkpoint and restore.
If you don't already  have `criu` installed, you can build it from source, following the
[online instructions](http://criu.org/Installation). `criu` is also installed in the docker image
generated when building libcontainer with docker.


## Copyright and license

Code and documentation copyright 2014 Docker, inc.
The code and documentation are released under the [Apache 2.0 license](../LICENSE).
The documentation is also released under Creative Commons Attribution 4.0 International License.
You may obtain a copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.

---

### Overview (`man/README.md`)

runc man pages
====================

This directory contains man pages for runc in markdown format.

To generate man pages from it, use this command

    ./md2man-all.sh

You will see man pages generated under the man8 directory.

---

### Overview (`libcontainer/nsenter/README.md`)

## nsenter

The `nsenter` package registers a special init constructor that is called before
the Go runtime has a chance to boot.  This provides us the ability to `setns` on
existing namespaces and avoid the issues that the Go runtime has with multiple
threads.  This constructor will be called if this package is registered,
imported, in your go application.

The `nsenter` package will `import "C"` and it uses [cgo](https://golang.org/cmd/cgo/)
package. In cgo, if the import of "C" is immediately preceded by a comment, that comment,
called the preamble, is used as a header when compiling the C parts of the package.
So every time we  import package `nsenter`, the C code function `nsexec()` would be
called. And package `nsenter` is only imported in `init.go`, so every time the runc
`init` command is invoked, that C code is run.

Because `nsexec()` must be run before the Go runtime in order to use the
Linux kernel namespace, you must `import` this library into a package if
you plan to use `libcontainer` directly. Otherwise Go will not execute
the `nsexec()` constructor, which means that the re-exec will not cause
the namespaces to be joined. You can import it like this:

```go
import _ "github.com/opencontainers/runc/libcontainer/nsenter"
```

`nsexec()` will first get the file descriptor number for the init pipe
from the environment variable `_LIBCONTAINER_INITPIPE` (which was opened
by the parent and kept open across the fork-exec of the `nsexec()` init
process). The init pipe is used to read bootstrap data (namespace paths,
clone flags, uid and gid mappings, and the console path) from the parent
process. `nsexec()` will then call `setns(2)` to join the namespaces
provided in the bootstrap data (if available), `clone(2)` a child process
with the provided clone flags, update the user and group ID mappings, do
some further miscellaneous setup steps, and then send the PID of the
child process to the parent of the `nsexec()` "caller". Finally,
the parent `nsexec()` will exit and the child `nsexec()` process will
return to allow the Go runtime take over.

NOTE: We do both `setns(2)` and `clone(2)` even if we don't have any
`CLONE_NEW*` clone flags because we must fork a new process in order to
enter the PID namespace.

---

### Overview (`tests/cmd/README.md`)

These are helpers used by [integration tests](/tests/integration).

They are compiled from the top-level Makefile via `make test-binaries`,
and the resulting binaries can be found in `./_bin`.

---

### Overview (`tests/integration/README.md`)

# runc Integration Tests

Integration tests provide end-to-end testing of runc.

Note that integration tests do **not** replace unit tests.

As a rule of thumb, code should be tested thoroughly with unit tests.
Integration tests on the other hand are meant to test a specific feature end
to end.

Integration tests are written in *bash* using the
[bats (Bash Automated Testing System)](https://github.com/bats-core/bats-core)
framework. Please see
[bats documentation](https://bats-core.readthedocs.io/en/stable/index.html)
for more details.

## Running integration tests

The easiest way to run integration tests is with Docker:
```bash
make integration
```
Alternatively, you can run integration tests directly on your host through make:
```bash
sudo make localintegration
```
Or you can just run them directly using bats
```bash
sudo bats tests/integration
```
To run a single test bucket:
```bash
make integration TESTPATH="/checkpoint.bats"
```


To run them on your host, you need to set up a development environment plus
[bats (Bash Automated Testing System)](https://github.com/bats-core/bats-core#installing-bats-from-source).

For example:
```bash
cd ~/go/src/github.com
git clone https://github.com/bats-core/bats-core.git
cd bats-core
./install.sh /usr/local
```

## Writing integration tests

[Helper functions](https://github.com/opencontainers/runc/blob/master/tests/integration/helpers.bash)
are provided in order to facilitate writing tests.

Call runc (and any other command) via bats' `run` helper, giving the expected
exit code, and check its output with the assertion helpers:

```bash
run -0 runc list -q
assert_line --index 0 "test_box1"

run ! runc state test_busybox
assert_output --partial "does not exist"
```

The `-N` argument to `run` makes bats fail the test unless the command exits
with code N, and `run !` unless it fails with any non-zero code. Use `run -0`
for a command that has to succeed; a bare `run` accepts any exit code, so use
it only where the exit code is genuinely irrelevant.

The available assertions, a subset of the
[bats-assert](https://github.com/bats-core/bats-assert) API implemented in
[lib/assert.bash](https://github.com/opencontainers/runc/blob/master/tests/integration/lib/assert.bash),
are:

```bash
assert_output [--partial | --regexp] EXPECTED
refute_output [--partial | --regexp] UNEXPECTED
assert_line --index IDX [--partial | --regexp] EXPECTED
```

Prefer these over `[ ... ]` or `[[ ... ]]` comparisons: when an assertion
fails, the test log shows both the expected and the actual value, while a bare
test expression only shows the expression itself.

Please see existing tests for examples.

---

### Overview (`tests/cmd/seccompagent/README.md`)

# Seccomp Agent

## Warning

Please note this is an example agent, as such it is possible that specially
crafted messages can produce bad behaviour. Please use it as an example only.

Also, this agent is used for integration tests. Be aware that changing the
behaviour can break the integration tests.

## Get started

Compile runc and seccompagent:
```bash
make runc seccompagent
```

Run the seccomp agent in the background:
```bash
sudo ./tests/cmd/_bin/seccompagent &
```

Prepare a container:
```bash
mkdir container-seccomp-notify
cd container-seccomp-notify
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -
```

Then, generate a config.json by running the script gen-seccomp-example-cfg.sh
from the directory where this README.md is in the container directory you
prepared earlier (`container-seccomp-notify`).

Then start the container:
```bash
runc run mycontainerid
```

The container will output something like this:
```bash
+ cd /dev/shm
+ mkdir test-dir
+ touch test-file
+ chmod 777 test-file
chmod: changing permissions of 'test-file': No medium found
+ stat /dev/shm/test-dir-foo
  File: /dev/shm/test-dir-foo
  Size: 40        	Blocks: 0          IO Block: 4096   directory
Device: 3eh/62d	Inode: 2           Links: 2
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2021-09-09 15:03:13.043716040 +0000
Modify: 2021-09-09 15:03:13.043716040 +0000
Change: 2021-09-09 15:03:13.043716040 +0000
 Birth: -
+ ls -l /dev/shm
total 0
drwxr-xr-x 2 root root 40 Sep  9 15:03 test-dir-foo
-rw-r--r-- 1 root root  0 Sep  9 15:03 test-file
+ echo Note the agent added a suffix for the directory name and chmod fails
Note the agent added a suffix for the directory name and chmod fails
```

This shows a simple example that runs in /dev/shm just because it is a tmpfs in
the example config.json.

The agent makes all chmod calls fail with ENOMEDIUM, as the example output shows.

For mkdir, the agent adds a "-foo" suffix: the container runs "mkdir test-dir"
but the directory created is "test-dir-foo".

---

### Overview (`vendor/github.com/aperturerobotics/protobuf-go-lite/README.md`)

# protobuf-go-lite

[![GoDoc Widget]][GoDoc] [![Go Report Card Widget]][Go Report Card] [![DeepWiki Widget]][DeepWiki]

[GoDoc]: https://godoc.org/github.com/aperturerobotics/protobuf-go-lite
[GoDoc Widget]: https://godoc.org/github.com/aperturerobotics/protobuf-go-lite?status.svg
[Go Report Card Widget]: https://goreportcard.com/badge/github.com/aperturerobotics/protobuf-go-lite
[Go Report Card]: https://goreportcard.com/report/github.com/aperturerobotics/protobuf-go-lite
[DeepWiki Widget]: https://img.shields.io/badge/DeepWiki-aperturerobotics%2Fprotobuf--go--lite-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==
[DeepWiki]: https://deepwiki.com/aperturerobotics/protobuf-go-lite

**protobuf-go-lite** is a stripped-down version of the [protobuf-go] code
generator modified to work without reflection and merged with [vtprotobuf] to
provide modular features with static code generation for marshal/unmarshal,
size, clone, equal, text, and JSON. JSON support is derived from a fork of
[protoc-gen-go-json].

[protobuf-go]: https://github.com/protocolbuffers/protobuf-go
[vtprotobuf]: https://github.com/planetscale/vtprotobuf
[protoc-gen-go-json]: https://github.com/TheThingsIndustries/protoc-gen-go-json

Static code generation without reflection is more efficient at runtime and
results in smaller code binaries. It also provides better support for [tinygo]
which has limited reflection support.

[tinygo]: https://github.com/tinygo-org/tinygo

protobuf-go-lite supports Edition 2024 schemas that resolve to the open Go API
and static, reflect-free generated output. The default `features=all` path
supports explicit and implicit presence, legacy required fields, packed
encoding, delimited message encoding, oneofs, maps, clone/equal, text,
unmarshal, unsafe unmarshal, and JSON when the resolved JSON format is
`ALLOW`.

Generated output is static Go code. The default `codegen=helper` mode emits
message methods that call small concrete helpers from the root
`protobuf-go-lite` runtime package to keep generated `.pb.go` files smaller.
The fallback `codegen=unrolled` mode keeps the older inline method-body shape
for helper-converted method families when callers need to inspect or compare
that output. Neither mode relies on Go reflection, descriptors, struct tags, or
runtime type metadata for generated marshal, unmarshal, size, clone, equal,
text, or JSON behavior.

protobuf-go-lite rejects Edition schemas that require closed enum semantics,
`LEGACY_BEST_EFFORT` JSON, or explicit hybrid/opaque Go APIs. It does not
support fieldmasks and extensions.

### Ecosystem

Lightweight Protobuf 3 RPCs are implemented in [StaRPC] for Go and TypeScript.

[StaRPC]: https://github.com/aperturerobotics/starpc

[protoc-gen-doc] is recommended for generating documentation.

[protoc-gen-doc]: https://github.com/pseudomuto/protoc-gen-doc

[protobuf-es-lite] is recommended for lightweight TypeScript protobufs.

[protobuf-es-lite]: https://github.com/aperturerobotics/protobuf-es-lite

## Protobuf

[protocol buffers](https://protobuf.dev) are a cross-platform cross-language
message serialization format. Protobuf is a language for specifying the schema
for structured data. This schema is compiled into language specific bindings.
This project provides both a tool to generate Go code for the protocol buffer
language, and also the runtime implementation to handle serialization of
messages in Go.

See the [protocol buffer developer guide](https://protobuf.dev/overview) for
more information about protocol buffers themselves.

## Example

See the [protobuf-project](https://github.com/aperturerobotics/protobuf-project)
template for an example of how to use this package and vtprotobuf together with
protowrap to generate protobufs for your project.

This package is available at **github.com/aperturerobotics/protobuf-go-lite**.

## Package index

Summary of the packages provided by this module:

*   [`compiler/protogen`](https://pkg.go.dev/github.com/aperturerobotics/protobuf-go-lite/compiler/protogen):
    Package `protogen` provides support for writing protoc plugins.
*   [`cmd/protoc-gen-go-lite`](https://pkg.go.dev/github.com/aperturerobotics/protobuf-go-lite/cmd/protoc-gen-go-lite):
    The `protoc-gen-go-lite` binary is a protoc plugin to generate a Go protocol
    buffer package.

## Usage

1. Install `protoc-gen-go-lite`:

    ```
    go install github.com/aperturerobotics/protobuf-go-lite/cmd/protoc-gen-go-lite@latest
    ```

2. Update your `protoc` generator to use the new plug-in.

    ```
    for name in $(PROTO_SRC_NAMES); do \
        protoc \
          --plugin protoc-gen-go-lite="${GOBIN}/protoc-gen-go-lite" \
          --go-lite_out=.  \
          --go-lite_opt=features=marshal+unmarshal+size+equal+clone+text \
        proto/$${name}.proto; \
    done
    ```

`protobuf-go-lite` replaces `protoc-gen-go` and `protoc-gen-go-vtprotobuf` and should not be used with those generators.

Check out the [template](https://github.com/aperturerobotics/template) for a quick start!

### Code generation modes

`protoc-gen-go-lite` accepts `codegen=helper` and `codegen=unrolled`:

- `codegen=helper` is the default. It emits static message methods that call
  concrete runtime helpers such as encode, decode, clone/equal, size, and text
  helpers.
- `codegen=unrolled` emits the older inline method-body style for
  helper-converted method families. Select it by adding `codegen=unrolled` to
  `--go-lite_opt`.

Both modes are selected at generation time and produce normal Go packages for
callers. They do not add a reflection registry, descriptor builder, struct tag
interpreter, or runtime type-metadata dependency to generated fast paths.

### Generated output

Generated `.pb.go` files are checked in for this repository's fixtures and
well-known type packages. After changing the generator or runtime helpers,
regenerate and verify them with the GNU Make targets:

```
gmake gengo
gmake check-gengo
```

On systems where `make` is GNU Make, `make check-gengo` is equivalent. On macOS,
use `gmake` so the same GNU Make behavior is used locally and in Linux CI.

## Available features

The following additional features can be enabled:

- `size`: generates a `func (p *YourProto) SizeVT() int` helper that behaves identically to calling `proto.Size(p)` on the message, except the size calculation is static generated code and does not use reflection. This helper function can be used directly, and it'll also be used by the `marshal` codegen to ensure the destination buffer is properly sized before ProtoBuf objects are marshalled to it.

- `equal`: generates the following helper methods

    - `func (this *YourProto) EqualVT(that *YourProto) bool`: this function behaves almost identically to calling `proto.Equal(this, that)` on messages, except the equality calculation is static generated code and does not use reflection. This helper function can be used directly.

    - `func (this *YourProto) EqualMessageVT(thatMsg any) bool`: this function behaves like the above `this.EqualVT(that)`, but allows comparing against arbitrary proto messages. If `thatMsg` is not of type `*YourProto`, false is returned. The uniform signature provided by this method allows accessing this method via type assertions even if the message type is not known at compile time. This allows implementing a generic `func EqualVT(proto.Message, proto.Message) bool` without reflection.

- `marshal`: generates the following helper methods

    - `func (p *YourProto) MarshalVT() ([]byte, error)`: this function behaves identically to calling `proto.Marshal(p)`, except the actual marshalling is static generated code and does not use reflection or allocate memory. This function simply allocates a properly sized buffer by calling `SizeVT` on the message and then uses `MarshalToSizedBufferVT` to marshal to it.

    - `func (p *YourProto) MarshalToVT(data []byte) (int, error)`: this function can be used to marshal a message to an existing buffer. The buffer must be large enough to hold the marshalled message, otherwise this function will panic. It returns the number of bytes marshalled. This function is useful e.g. when using memory pooling to re-use serialization buffers.

    - `func (p *YourProto) MarshalToSizedBufferVT(data []byte) (int, error)`: this function behaves like `MarshalTo` but expects that the input buffer has the exact size required to hold the message, otherwise it will panic.

- `marshal_strict`: generates the following helper methods

    - `func (p *YourProto) MarshalVTStrict() ([]byte, error)`: this function behaves like `MarshalVT`, except fields are marshalled in a strict order by field's numbers they were declared in .proto file.

    - `func (p *YourProto) MarshalToVTStrict(data []byte) (int, error)`: this function behaves like `MarshalToVT`, except fields are marshalled in a strict order by field's numbers they were declared in .proto file.

    - `func (p *YourProto) MarshalToSizedBufferVTStrict(data []byte) (int, error)`: this function behaves like `MarshalToSizedBufferVT`, except fields are marshalled in a strict order by field's numbers they were declared in .proto file.


- `unmarshal`: generates a `func (p *YourProto) UnmarshalVT(data []byte)` that behaves similarly to calling `proto.Unmarshal(data, p)` on the message, except the unmarshalling is performed by static generated code without using reflection and allocating as little memory as possible. If the receiver `p` is **not** fully zeroed-out, the unmarshal call will actually behave like `proto.Merge(data, p)`. This is because the `proto.Unmarshal` in the ProtoBuf API is implemented by resetting the destination message and then calling `proto.Merge` on it. To ensure proper `Unmarshal` semantics, ensure you've called `proto.Reset` on your message before calling `UnmarshalVT`, or that your message has been newly allocated.

- `unmarshal_unsafe` generates a `func (p *YourProto) UnmarshalVTUnsafe(data []byte)` that behaves like `UnmarshalVT`, except it unsafely casts slices of data to `bytes` and `string` fields instead of copying them to newly allocated arrays, so that it performs less allocations. **Data received from the wire has to be left untouched for the lifetime of the message.** Otherwise, the message's `bytes` and `string` fields can be corrupted.

- `clone`: generates the following helper methods

    - `func (p *YourProto) CloneVT() *YourProto`: this function behaves similarly to calling `proto.Clone(p)` on the message, except the cloning is performed by static generated code without using reflection. If the receiver `p` is `nil` a typed `nil` is returned.

    - `func (p *YourProto) CloneMessageVT() any`: this function behaves like the above `p.CloneVT()`, but provides a uniform signature in order to be accessible via type assertions even if the type is not known at compile time. This allows implementing a generic `func CloneMessageVT() any` without reflection. If the receiver `p` is `nil`, a typed `nil` pointer of the message type will be returned inside a `any` interface.

- `json`: generates the following helper methods

    - `func (p *YourProto) UnmarshalJSON(data []byte) error` behaves similarly to calling `protojson.Unmarshal(data, p)` on the message, except the unmarshalling is performed by static generated code without using reflection and allocating as little memory as possible. If the receiver `p` is **not** fully zeroed-out, the unmarshal call will actually behave like `proto.Merge(data, p)`. To ensure proper `Unmarshal` semantics, ensure you've called `proto.Reset` on your message before calling `UnmarshalJSON`, or that your message has been newly allocated.

    - `func (p *YourProto) UnmarshalJSONValue(val *fastjson.Value) error` unmarshals a `*fastjson.Value`.

    - `func (p *YourProto) MarshalJSON() ([]byte, error)` behaves similarly to calling `protojson.Marshal(p)` on the message, except the marshalling is performed by static generated code without using reflection and allocating as little memory as possible.

    - Adding a `//protobuf-go-lite:disable-json` comment before a message or enum will disable the json marshaler / unmarshaler.

- `text`: generates `MarshalProtoText() string` and `String() string` methods
  that emit protobuf text-format-style output using static generated code
  without reflection. Adding a `//protobuf-go-lite:disable-text` comment before
  a message disables text generation for that message.

## License

BSD-3

---

### Overview (`vendor/github.com/containerd/console/README.md`)

# console

[](https://pkg.go.dev/github.com/containerd/console)
[](https://github.com/containerd/console/actions?query=workflow%3ACI)
[](https://goreportcard.com/report/github.com/containerd/console)

Golang package for dealing with consoles.  Light on deps and a simple API.

## Modifying the current process

```go
current := console.Current()
defer current.Reset()

if err := current.SetRaw(); err != nil {
}
ws, err := current.Size()
current.Resize(ws)
```

## Project details

console is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
As a containerd sub-project, you will find the:
 * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
 * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
 * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)

information in our [`containerd/project`](https://github.com/containerd/project) repository.

---

### Overview (`vendor/github.com/cyphar/filepath-securejoin/README.md`)

## `filepath-securejoin` ##

[](https://pkg.go.dev/github.com/cyphar/filepath-securejoin)
[](https://github.com/cyphar/filepath-securejoin/actions/workflows/ci.yml)

### Old API ###

This library was originally just an implementation of `SecureJoin` which was
[intended to be included in the Go standard library][go#20126] as a safer
`filepath.Join` that would restrict the path lookup to be inside a root
directory.

The implementation was based on code that existed in several container
runtimes. Unfortunately, this API is **fundamentally unsafe** against attackers
that can modify path components after `SecureJoin` returns and before the
caller uses the path, allowing for some fairly trivial TOCTOU attacks.

`SecureJoin` (and `SecureJoinVFS`) are still provided by this library to
support legacy users, but new users are strongly suggested to avoid using
`SecureJoin` and instead use the [new api](#new-api) or switch to
[libpathrs][libpathrs].

With the above limitations in mind, this library guarantees the following:

* If no error is set, the resulting string **must** be a child path of
  `root` and will not contain any symlink path components (they will all be
  expanded).

* When expanding symlinks, all symlink path components **must** be resolved
  relative to the provided root. In particular, this can be considered a
  userspace implementation of how `chroot(2)` operates on file paths. Note that
  these symlinks will **not** be expanded lexically (`filepath.Clean` is not
  called on the input before processing).

* Non-existent path components are unaffected by `SecureJoin` (similar to
  `filepath.EvalSymlinks`'s semantics).

* The returned path will always be `filepath.Clean`ed and thus not contain any
  `..` components.

A (trivial) implementation of this function on GNU/Linux systems could be done
with the following (note that this requires root privileges and is far more
opaque than the implementation in this library, and also requires that
`readlink` is inside the `root` path and is trustworthy):

```go
package securejoin

import (
	"os/exec"
	"path/filepath"
)

func SecureJoin(root, unsafePath string) (string, error) {
	unsafePath = string(filepath.Separator) + unsafePath
	cmd := exec.Command("chroot", root,
		"readlink", "--canonicalize-missing", "--no-newline", unsafePath)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}
	expanded := string(output)
	return filepath.Join(root, expanded), nil
}
```

[libpathrs]: https://github.com/openSUSE/libpathrs
[go#20126]: https://github.com/golang/go/issues/20126

### <a name="new-api" /> New API ###
[#new-api]: #new-api

While we recommend users switch to [libpathrs][libpathrs] as soon as it has a
stable release, some methods implemented by libpathrs have been ported to this
library to ease the transition. These APIs are only supported on Linux.

These APIs are implemented such that `filepath-securejoin` will
opportunistically use certain newer kernel APIs that make these operations far
more secure. In particular:

* All of the lookup operations will use [`openat2`][openat2.2] on new enough
  kernels (Linux 5.6 or later) to restrict lookups through magic-links and
  bind-mounts (for certain operations) and to make use of `RESOLVE_IN_ROOT` to
  efficiently resolve symlinks within a rootfs.

* The APIs provide hardening against a malicious `/proc` mount to either detect
  or avoid being tricked by a `/proc` that is not legitimate. This is done
  using [`openat2`][openat2.2] for all users, and privileged users will also be
  further protected by using [`fsopen`][fsopen.2] and [`open_tree`][open_tree.2]
  (Linux 5.2 or later).

[openat2.2]: https://www.man7.org/linux/man-pages/man2/openat2.2.html
[fsopen.2]: https://github.com/brauner/man-pages-md/blob/main/fsopen.md
[open_tree.2]: https://github.com/brauner/man-pages-md/blob/main/open_tree.md

#### `OpenInRoot` ####

```go
func OpenInRoot(root, unsafePath string) (*os.File, error)
func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error)
func Reopen(handle *os.File, flags int) (*os.File, error)
```

`OpenInRoot` is a much safer version of

```go
path, err := securejoin.SecureJoin(root, unsafePath)
file, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC)
```

that protects against various race attacks that could lead to serious security
issues, depending on the application. Note that the returned `*os.File` is an
`O_PATH` file descriptor, which is quite restricted. Callers will probably need
to use `Reopen` to get a more usable handle (this split is done to provide
useful features like PTY spawning and to avoid users accidentally opening bad
inodes that could cause a DoS).

Callers need to be careful in how they use the returned `*os.File`. Usually it
is only safe to operate on the handle directly, and it is very easy to create a
security issue. [libpathrs][libpathrs] provides far more helpers to make using
these handles safer -- there is currently no plan to port them to
`filepath-securejoin`.

`OpenatInRoot` is like `OpenInRoot` except that the root is provided using an
`*os.File`. This allows you to ensure that multiple `OpenatInRoot` (or
`MkdirAllHandle`) calls are operating on the same rootfs.

> **NOTE**: Unlike `SecureJoin`, `OpenInRoot` will error out as soon as it hits
> a dangling symlink or non-existent path. This is in contrast to `SecureJoin`
> which treated non-existent components as though they were real directories,
> and would allow for partial resolution of dangling symlinks. These behaviours
> are at odds with how Linux treats non-existent paths and dangling symlinks,
> and so these are no longer allowed.

#### `MkdirAll` ####

```go
func MkdirAll(root, unsafePath string, mode int) error
func MkdirAllHandle(root *os.File, unsafePath string, mode int) (*os.File, error)
```

`MkdirAll` is a much safer version of

```go
path, err := securejoin.SecureJoin(root, unsafePath)
err = os.MkdirAll(path, mode)
```

that protects against the same kinds of races that `OpenInRoot` protects
against.

`MkdirAllHandle` is like `MkdirAll` except that the root is provided using an
`*os.File` (the reason for this is the same as with `OpenatInRoot`) and an
`*os.File` of the final created directory is returned (this directory is
guaranteed to be effectively identical to the directory created by
`MkdirAllHandle`, which is not possible to ensure by just using `OpenatInRoot`
after `MkdirAll`).

> **NOTE**: Unlike `SecureJoin`, `MkdirAll` will error out as soon as it hits
> a dangling symlink or non-existent path. This is in contrast to `SecureJoin`
> which treated non-existent components as though they were real directories,
> and would allow for partial resolution of dangling symlinks. These behaviours
> are at odds with how Linux treats non-existent paths and dangling symlinks,
> and so these are no longer allowed. This means that `MkdirAll` will not
> create non-existent directories referenced by a dangling symlink.

### License ###

`SPDX-License-Identifier: BSD-3-Clause AND MPL-2.0`

Some of the code in this project is derived from Go, and is licensed under a
BSD 3-clause license (available in `LICENSE.BSD`). Other files (many of which
are derived from [libpathrs][libpathrs]) are licensed under the Mozilla Public
License version 2.0 (available in `LICENSE.MPL-2.0`). If you are using the
["New API" described above][#new-api], you are probably using code from files
released under this license.

Every source file in this project has a copyright header describing its
license. Please check the license headers of each file to see what license
applies to it.

See [COPYING.md](./COPYING.md) for some more details.

[umoci]: https://github.com/opencontainers/umoci

---

### Overview (`vendor/github.com/docker/go-units/README.md`)

[](https://godoc.org/github.com/docker/go-units)

# Introduction

go-units is a library to transform human friendly measurements into machine friendly values.

## Usage

See the [docs in godoc](https://godoc.org/github.com/docker/go-units) for examples and documentation.

## Copyright and license

Copyright © 2015 Docker, Inc.

go-units is licensed under the Apache License, Version 2.0.
See [LICENSE](LICENSE) for the full text of the license.

---

### Overview (`vendor/github.com/mrunalp/fileutils/README.md`)

# fileutils

Collection of utilities for file manipulation in golang

The library is based on docker pkg/archive pkg/idtools but does copies instead of handling archive formats.

---

### Overview (`vendor/github.com/opencontainers/cgroups/README.md`)

# OCI Project Template

Useful boilerplate and organizational information for all OCI projects.

* README (this file)
* [The Apache License, Version 2.0](LICENSE)
* [A list of maintainers](MAINTAINERS)
* [Maintainer guidelines](MAINTAINERS_GUIDE.md)
* [Contributor guidelines](CONTRIBUTING.md)
* [Project governance](GOVERNANCE.md)
* [Release procedures](RELEASES.md)

---

### Overview (`vendor/github.com/seccomp/libseccomp-golang/README.md`)

===============================================================================
https://github.com/seccomp/libseccomp-golang

[](https://pkg.go.dev/github.com/seccomp/libseccomp-golang)
[](https://github.com/seccomp/libseccomp-golang/actions/workflows/validate.yml)
[](https://github.com/seccomp/libseccomp-golang/actions/workflows/test.yml)

The libseccomp library provides an easy to use, platform independent, interface
to the Linux Kernel's syscall filtering mechanism.  The libseccomp API is
designed to abstract away the underlying BPF based syscall filter language and
present a more conventional function-call based filtering interface that should
be familiar to, and easily adopted by, application developers.

The libseccomp-golang library provides a Go based interface to the libseccomp
library.

## Online Resources

The library source repository currently lives on GitHub at the following URLs:

* https://github.com/seccomp/libseccomp-golang
* https://github.com/seccomp/libseccomp

Documentation for this package is also available at:

* https://pkg.go.dev/github.com/seccomp/libseccomp-golang

## Verifying Releases

Starting with libseccomp-golang v0.10.0, the git tag corresponding to each
release should be signed by one of the libseccomp-golang maintainers.  It is
recommended that before use you verify the release tags using the following
command:

	% git tag -v <tag>

At present, only the following keys, specified via the fingerprints below, are
authorized to sign official libseccomp-golang release tags:

	Paul Moore <paul@paul-moore.com>
	7100 AADF AE6E 6E94 0D2E  0AD6 55E4 5A5A E8CA 7C8A

	Tom Hromatka <tom.hromatka@oracle.com>
	47A6 8FCE 37C7 D702 4FD6  5E11 356C E62C 2B52 4099

	Kir Kolyshkin <kolyshkin@gmail.com>
	C242 8CD7 5720 FACD CF76  B6EA 17DE 5ECB 75A1 100E

More information on GnuPG and git tag verification can be found at their
respective websites: https://git-scm.com/docs/git and https://gnupg.org.

## Installing the package

	% go get github.com/seccomp/libseccomp-golang

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).

---

### Overview (`vendor/github.com/sirupsen/logrus/README.md`)

# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://github.com/sirupsen/logrus/actions?query=workflow%3ACI) [](https://pkg.go.dev/github.com/sirupsen/logrus)

Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger.

**Logrus is in maintenance mode.** The project focuses on security, bug fixes,
and performance improvements. New features are not planned, aside from changes
required to provide interoperability with other logging ecosystems (e.g., Go's
[log/slog](https://pkg.go.dev/log/slog)).

I believe Logrus' biggest contribution is to have played a part in today's
widespread use of structured logging in Golang. There doesn't seem to be a
reason to do a major, breaking iteration into Logrus V2, since the fantastic Go
community has built those independently. Many fantastic alternatives have sprung
up. Logrus would look like those, had it been re-designed with what we know
about structured logging in Go today. Check out, for example,
[Zerolog][zerolog], [Zap][zap], and [Apex][apex].

[zerolog]: https://github.com/rs/zerolog
[zap]: https://github.com/uber-go/zap
[apex]: https://github.com/apex/log

Nicely color-coded in development (when a TTY is attached, otherwise just
plain text):



With `logrus.SetFormatter(&logrus.JSONFormatter{})`, for easy parsing by logstash
or Splunk:

```json lines
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
{"level":"warning","msg":"The group's number increased tremendously!","number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
{"animal":"walrus","level":"info","msg":"A giant walrus appears!","size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.","size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
```

With the default `logrus.SetFormatter(&logrus.TextFormatter{})` when a TTY is not
attached, the output is compatible with the
[logfmt](https://pkg.go.dev/github.com/kr/logfmt) format:

```bash
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" animal=orca err="It's over 9000!" number=100 omg=true size=9009
```

To ensure this behaviour even if a TTY is attached, set your formatter as follows:

```go
logrus.SetFormatter(&logrus.TextFormatter{
    DisableColors: true,
    FullTimestamp: true,
})
```

#### Logging Method Name

If you wish to add the calling method as a field, instruct the logger via:

```go
logrus.SetReportCaller(true)
```

This adds the caller as 'method' like so:

```json
{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by","time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
```

```bash
time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin
```

Note that this does add measurable overhead - the cost will depend on the version of Go, but is
between 20 and 40% in recent tests with 1.6 and 1.7.  You can validate this in your
environment via benchmarks:

```bash
go test -bench=ReportCaller
```

#### Case-sensitivity

The organization's name was [changed to lower-case][1]. If you are getting import
conflicts due to case sensitivity, please use the lower-case import:
`github.com/sirupsen/logrus`.

[1]: https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276

#### Example

The simplest way to use Logrus is simply the package-level exported logger:

```go
package main

import "github.com/sirupsen/logrus"

func main() {
  logrus.WithFields(logrus.Fields{
    "animal": "walrus",
  }).Info("A walrus appears")
}
```

Note that it's completely api-compatible with the stdlib logger, so you can
replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"`
and you'll now have the flexibility of Logrus. You can customize it all you
want:

```go
package main

import (
  "os"

  log "github.com/sirupsen/logrus"
)

func init() {
  // Log as JSON instead of the default ASCII formatter.
  log.SetFormatter(&log.JSONFormatter{})

  // Output to stdout instead of the default stderr
  // Can be any io.Writer, see below for File example
  log.SetOutput(os.Stdout)

  // Only log the warning severity or above.
  log.SetLevel(log.WarnLevel)
}

func main() {
  log.WithFields(log.Fields{
    "animal": "walrus",
    "size":   10,
  }).Info("A group of walrus emerges from the ocean")

  log.WithFields(log.Fields{
    "omg":    true,
    "number": 122,
  }).Warn("The group's number increased tremendously!")

  log.WithFields(log.Fields{
    "omg":    true,
    "number": 100,
  }).Fatal("The ice breaks!")

  // A common pattern is to re-use fields between logging statements by re-using
  // the logrus.Entry returned from WithFields()
  contextLogger := log.WithFields(log.Fields{
    "common": "this is a common field",
    "other": "I also should be logged always",
  })

  contextLogger.Info("I'll be logged with common and other field")
  contextLogger.Info("Me too")
}
```

For more advanced usage such as logging to multiple locations from the same
application, you can also create an instance of the `logrus` Logger:

```go
package main

import (
  "os"

  "github.com/sirupsen/logrus"
)

// Create a new instance of the logger. You can have any number of instances.
var logger = logrus.New()

func main() {
  // The API for setting attributes is a little different than the package level
  // exported logger. See Godoc. 
  logger.Out = os.Stdout

  // You could set this to any `io.Writer` such as a file
  // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  // if err == nil {
  //  logger.Out = file
  // } else {
  //  logger.Info("Failed to log to file, using default stderr")
  // }

  logger.WithFields(logrus.Fields{
    "animal": "walrus",
    "size":   10,
  }).Info("A group of walrus emerges from the ocean")
}
```

#### Fields

Logrus encourages careful, structured logging through logging fields instead of
long, unparseable error messages. For example, instead of: `logrus.Fatalf("Failed
to send event %s to topic %s with key %d")`, you should log the much more
discoverable:

```go
logrus.WithFields(logrus.Fields{
  "event": event,
  "topic": topic,
  "key": key,
}).Fatal("Failed to send event")
```

We've found this API forces you to think about logging in a way that produces
much more useful logging messages. We've been in countless situations where just
a single added field to a log statement that was already there would've saved us
hours. The `WithFields` call is optional.

In general, with Logrus using any of the `printf`-family functions should be
seen as a hint you should add a field, however, you can still use the
`printf`-family functions with Logrus.

#### Default Fields

Often it's helpful to have fields _always_ attached to log statements in an
application or parts of one. For example, you may want to always log the
`request_id` and `user_ip` in the context of a request. Instead of writing
`logger.WithFields(logrus.Fields{"request_id": request_id, "user_ip": user_ip})` on
every line, you can create a `logrus.Entry` to pass around instead:

```go
requestLogger := logger.WithFields(logrus.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") // will log request_id and user_ip
requestLogger.Warn("something not great happened")
```

#### Hooks

You can add hooks for logging levels. For example to send errors to an exception
tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
multiple places simultaneously, e.g. syslog.

Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
`init`:

```go
package main

import (
  "log/syslog"

  "github.com/sirupsen/logrus"
  airbrake "gopkg.in/gemnasium/logrus-airbrake-hook.v2"
  logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
)

func init() {

  // Use the Airbrake hook to report errors that have Error severity or above to
  // an exception tracker. You can create custom hooks, see the Hooks section.
  logrus.AddHook(airbrake.NewHook(123, "xyz", "production"))

  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
  if err != nil {
    logrus.Error("Unable to connect to local syslog daemon")
  } else {
    logrus.AddHook(hook)
  }
}
```

Note: Syslog hooks also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).

A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)


#### Level logging

Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic.

```go
logrus.Trace("Something very low level.")
logrus.Debug("Useful debugging information.")
logrus.Info("Something noteworthy happened!")
logrus.Warn("You should probably take a look at this.")
logrus.Error("Something failed but I'm not quitting.")
// Calls os.Exit(1) after logging
logrus.Fatal("Bye.")
// Calls panic() after logging
logrus.Panic("I'm bailing.")
```

You can set the logging level on a `Logger`, then it will only log entries with
that severity or anything above it:

```go
// Will log anything that is info or above (warn, error, fatal, panic). Default.
logrus.SetLevel(logrus.InfoLevel)
```

It may be useful to set `logrus.Level = logrus.DebugLevel` in a debug or verbose
environment if your application has that.

Note: If you want different log levels for global (`logrus.SetLevel(...)`) and syslog logging, please check the [syslog hook README](hooks/syslog/README.md#different-log-levels-for-local-and-remote-logging).

#### Entries

Besides the fields added with `WithField` or `WithFields` some fields are
automatically added to all logging events:

1. `time`. The timestamp when the entry was created.
2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
   the `AddFields` call. E.g. `Failed to send event.`
3. `level`. The logging level. E.g. `info`.

#### Environments

Logrus has no notion of environment.

If you wish for hooks and formatters to only be used in specific environments,
you should handle that yourself. For example, if your application has a global
variable `Environment`, which is a string representation of the environment you
could do:

```go
import (
  "github.com/sirupsen/logrus"
)

func init() {
  // do something here to set environment depending on an environment variable
  // or command-line flag
  if Environment == "production" {
    logrus.SetFormatter(&logrus.JSONFormatter{})
  } else {
    // The TextFormatter is default, you don't actually have to do this.
    logrus.SetFormatter(&logrus.TextFormatter{})
  }
}
```

This configuration is how `logrus` was intended to be used, but JSON in
production is mostly only useful if you do log aggregation with tools like
Splunk or Logstash.

#### Formatters

The built-in logging formatters are:

* [`logrus.TextFormatter`](https://pkg.go.dev/github.com/sirupsen/logrus#TextFormatter)
  logs the event in colors if the logger output is a TTY, otherwise without colors.
  * To force colored output when there is no TTY, set the `ForceColors`
    field to `true`.  To force no colored output even if there is a TTY  set the
    `DisableColors` field to `true`.
  * On modern Windows terminals with ANSI (Virtual Terminal) support, TextFormatter
    automatically enables colored output.
  * If your environment does not support ANSI escape sequences, wrap the logger output
    using [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable)
    and set `ForceColors` (or `CLICOLOR_FORCE=1`) to enable colors through the wrapper.
  * When colors are enabled, levels are truncated to 4 characters by default. To disable
    truncation set the `DisableLevelTruncation` field to `true`.
  * When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text.
* [`logrus.JSONFormatter`](https://pkg.go.dev/github.com/sirupsen/logrus#JSONFormatter)
  logs fields as JSON.

Third-party logging formatters:

* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html).
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the Power of Zalgo.
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). get fileName, log's line number and the latest function's name when print log; Save log to files.
* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). logrus's message json formatter with human-readable caption added.
* [`easy-logrus-formatter`](https://github.com/WeiZhixiong/easy-logrus-formatter). Provide a user-friendly formatter for logrus.
* [`redactrus`](https://github.com/ibreakthecloud/redactrus). Redacts sensitive information like password, apikeys, email, etc. from logs.

You can define your formatter by implementing the `Formatter` interface,
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
`Fields` type (`map[string]any`) with all your fields as well as the
default ones (see Entries section above):

```go
type MyJSONFormatter struct{}

logrus.SetFormatter(new(MyJSONFormatter))

func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
  // Note this doesn't include Time, Level and Message which are available on
  // the Entry. Consult `godoc` on information about those fields or read the
  // source of the official loggers.
  serialized, err := json.Marshal(entry.Data)
    if err != nil {
      return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err)
    }
  return append(serialized, '\n'), nil
}
```

#### Logger as an `io.Writer`

Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it.

```go
w := logger.Writer()
defer w.Close()

srv := http.Server{
    // create a stdlib log.Logger that writes to
    // logrus.Logger.
    ErrorLog: log.New(w, "", 0),
}
```

Each line written to that writer will be printed the usual way, using formatters
and hooks. The level for those entries is `info`.

This means that we can override the standard library logger easily:

```go
logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}

// Use logrus for standard log output
// Note that `log` here references stdlib's log
// Not logrus imported under the name `log`.
log.SetOutput(logger.Writer())
```

#### Rotation

Log rotation is not provided with Logrus. Log rotation should be done by an
external program (like `logrotate(8)`) that can compress and delete old log
entries. It should not be a feature of the application-level logger.

#### Tools

| Tool | Description |
| ---- | ----------- |
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will be generated with different configs in different environments.|
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |

#### Testing

Logrus has a built-in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:

* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just adds the `test` hook
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):

```go
import(
  "testing"

  "github.com/sirupsen/logrus"
  "github.com/sirupsen/logrus/hooks/test"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t*testing.T){
  logger, hook := test.NewNullLogger()
  logger.Error("Helloerror")

  assert.Equal(t, 1, len(hook.Entries))
  assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
  assert.Equal(t, "Helloerror", hook.LastEntry().Message)

  hook.Reset()
  assert.Nil(t, hook.LastEntry())
}
```

#### Fatal handlers

Logrus can register one or more functions that will be called when any `fatal`
level message is logged. The registered handlers will be executed before
logrus performs an `os.Exit(1)`. This behavior may be helpful if callers need
to gracefully shut down. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.

```go
// ...
handler := func() {
  // gracefully shut down something...
}
logrus.RegisterExitHandler(handler)
// ...
```

#### Thread safety

By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs.
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.

Situations when locking is not needed include:

* You have no hooks registered, or hooks calling is already thread-safe.

* Writing to logger.Out is already thread-safe, for example:

  1) logger.Out is protected by locks.

  2) logger.Out is an os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing)

     (Refer to <http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/>)

---

### Overview (`vendor/github.com/vishvananda/netlink/README.md`)

# netlink - netlink library for go #

 [](https://godoc.org/github.com/vishvananda/netlink)

The netlink package provides a simple netlink library for go. Netlink
is the interface a user-space program in linux uses to communicate with
the kernel. It can be used to add and remove interfaces, set ip addresses
and routes, and configure ipsec. Netlink communication requires elevated
privileges, so in most cases this code needs to be run as root. Since
low-level netlink messages are inscrutable at best, the library attempts
to provide an api that is loosely modeled on the CLI provided by iproute2.
Actions like `ip link add` will be accomplished via a similarly named
function like AddLink(). This library began its life as a fork of the
netlink functionality in
[docker/libcontainer](https://github.com/docker/libcontainer) but was
heavily rewritten to improve testability, performance, and to add new
functionality like ipsec xfrm handling.

## Local Build and Test ##

You can use go get command:

    go get github.com/vishvananda/netlink

Testing dependencies:

    go get github.com/vishvananda/netns

Testing (requires root):

    sudo -E go test github.com/vishvananda/netlink

## Examples ##

Add a new bridge and add eth1 into it:

```go
package main

import (
    "fmt"
    "github.com/vishvananda/netlink"
)

func main() {
    la := netlink.NewLinkAttrs()
    la.Name = "foo"
    mybridge := &netlink.Bridge{LinkAttrs: la}
    err := netlink.LinkAdd(mybridge)
    if err != nil  {
        fmt.Printf("could not add %s: %v\n", la.Name, err)
    }
    eth1, _ := netlink.LinkByName("eth1")
    netlink.LinkSetMaster(eth1, mybridge)
}

```
Note `NewLinkAttrs` constructor, it sets default values in structure. For now
it sets only `TxQLen` to `-1`, so kernel will set default by itself. If you're
using simple initialization(`LinkAttrs{Name: "foo"}`) `TxQLen` will be set to
`0` unless you specify it like `LinkAttrs{Name: "foo", TxQLen: 1000}`.

Add a new ip address to loopback:

```go
package main

import (
    "github.com/vishvananda/netlink"
)

func main() {
    lo, _ := netlink.LinkByName("lo")
    addr, _ := netlink.ParseAddr("169.254.169.254/32")
    netlink.AddrAdd(lo, addr)
}

```

## Future Work ##

Many pieces of netlink are not yet fully supported in the high-level
interface. Aspects of virtually all of the high-level objects don't exist.
Many of the underlying primitives are there, so its a matter of putting
the right fields into the high-level objects and making sure that they
are serialized and deserialized correctly in the Add and List methods.

There are also a few pieces of low level netlink functionality that still
need to be implemented. Routing rules are not in place and some of the
more advanced link types. Hopefully there is decent structure and testing
in place to make these fairly straightforward to add.

---

### Overview (`vendor/github.com/vishvananda/netns/README.md`)

# netns - network namespaces in go #

The netns package provides an ultra-simple interface for handling
network namespaces in go. Changing namespaces requires elevated
privileges, so in most cases this code needs to be run as root.

## Local Build and Test ##

You can use go get command:

    go get github.com/vishvananda/netns

Testing (requires root):

    sudo -E go test github.com/vishvananda/netns

## Example ##

```go
package main

import (
    "fmt"
    "net"
    "runtime"

    "github.com/vishvananda/netns"
)

func main() {
    // Lock the OS Thread so we don't accidentally switch namespaces
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()

    // Save the current network namespace
    origns, _ := netns.Get()
    defer origns.Close()

    // Create a new network namespace
    newns, _ := netns.New()
    defer newns.Close()

    // Do something with the network namespace
    ifaces, _ := net.Interfaces()
    fmt.Printf("Interfaces: %v\n", ifaces)

    // Switch back to the original namespace
    netns.Set(origns)
}

```

---

### Overview (`vendor/github.com/checkpoint-restore/go-criu/v8/README.md`)

# go-criu -- Go bindings for CRIU

[](https://github.com/checkpoint-restore/go-criu/actions/workflows/main.yml)
[](https://github.com/checkpoint-restore/go-criu/actions/workflows/verify.yml)
[](https://pkg.go.dev/github.com/checkpoint-restore/go-criu)

This repository provides Go bindings for [CRIU](https://criu.org/).
The code is based on the Go-based PHaul implementation from the CRIU repository.
For easier inclusion into other Go projects, the CRIU Go bindings have been
moved to this repository.

## CRIU

The Go bindings provide an easy way to use the CRIU RPC calls from Go without
the need to set up all the infrastructure to make the actual RPC connection to CRIU.

The following example would print the version of CRIU:

```go
import (
	"log"

	"github.com/checkpoint-restore/go-criu/v8"
)

func main() {
	c := criu.MakeCriu()
	version, err := c.GetCriuVersion()
	if err != nil {
		log.Fatalln(err)
	}
	log.Println(version)
}
```

or to just check if at least a certain CRIU version is installed:

```go
	c := criu.MakeCriu()
	result, err := c.IsCriuAtLeast(31100)
```

## CRIT

The `crit` package provides bindings to decode, encode, and manipulate
CRIU image files natively within Go. It also provides a CLI tool similar
to the original CRIT Python tool. To get started with this, see the docs
at [CRIT (Go library)](https://criu.org/CRIT_%28Go_library%29).

## Releases

The first go-criu release was 3.11 based on CRIU 3.11. The initial plan
was to follow CRIU so that go-criu would carry the same version number as
CRIU.

As go-criu is imported in other projects and as Go modules are expected
to follow Semantic Versioning go-criu will also follow Semantic Versioning
starting with the 4.0.0 release.

The following table shows the relation between go-criu and criu versions:

| Major version  | Latest release | CRIU version |
| -------------- | -------------- | ------------ |
| v8             | 8.4.0          | 4.2          |
| v7             | 7.2.0          | 3.19         |
| v7             | 7.0.0          | 3.18         |
| v6             | 6.3.0          | 3.17         |
| v5             | 5.3.0          | 3.16         |
| v5             | 5.0.0          | 3.15         |
| v4             | 4.1.0          | 3.14         |

## How to contribute

See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this
project.

## License and copyright

Unless mentioned otherwise in a specific file's header, all code in
this project is released under the Apache 2.0 license.

The author of a change remains the copyright holder of their code
(no copyright assignment). The list of authors and contributors can be
retrieved from the git commit history and in some cases, the file headers.

---

### Overview (`vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/README.md`)

## `pathrs-lite` ##

`github.com/cyphar/filepath-securejoin/pathrs-lite` provides a minimal **pure
Go** implementation of the core bits of [libpathrs][]. This is not intended to
be a complete replacement for libpathrs, instead it is mainly intended to be
useful as a transition tool for existing Go projects.

`pathrs-lite` also provides a very easy way to switch to `libpathrs` (even for
downstreams where `pathrs-lite` is being used in a third-party package and is
not interested in using CGo). At build time, if you use the `libpathrs` build
tag then `pathrs-lite` will use `libpathrs` directly instead of the pure Go
implementation. The two backends are functionally equivalent (and we have
integration tests to verify this), so this migration should be very easy with
no user-visible impact.

[libpathrs]: https://github.com/cyphar/libpathrs

### License ###

Most of this subpackage is licensed under the Mozilla Public License (version
2.0). For more information, see the top-level [COPYING.md][] and
[LICENSE.MPL-2.0][] files, as well as the individual license headers for each
file.

```
Copyright (C) 2024-2025 Aleksa Sarai <cyphar@cyphar.com>
Copyright (C) 2024-2025 SUSE LLC

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
```

[COPYING.md]: ../COPYING.md
[LICENSE.MPL-2.0]: ../LICENSE.MPL-2.0

---

### Overview (`vendor/github.com/godbus/dbus/v5/README.md`)

dbus
----


dbus is a simple library that implements native Go client bindings for the
D-Bus message bus system.

### Features

* Complete native implementation of the D-Bus message protocol
* Go-like API (channels for signals / asynchronous method calls, Goroutine-safe connections)
* Subpackages that help with the introspection / property interfaces

### Usage

The complete package documentation and some simple examples are available at
[pkg.go.dev](https://pkg.go.dev/github.com/godbus/dbus/v5). Also, the
[\_examples](https://github.com/godbus/dbus/tree/master/_examples) directory
gives a short overview over the basic usage.

#### Projects using godbus
- [bluetooth](https://github.com/tinygo-org/bluetooth): cross-platform Bluetooth API for Go and TinyGo.
- [fyne](https://github.com/fyne-io/fyne): a cross platform GUI in Go inspired by Material Design.
- [fynedesk](https://github.com/fyne-io/fynedesk): a full desktop environment for Linux/Unix using Fyne.
- [go-systemd](https://github.com/coreos/go-systemd): Go bindings to systemd.
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.

Please note that the API is considered unstable for now and may change without
further notice.

### License

The library is available under the Simplified BSD License; see LICENSE for the full
text.

Nearly all of the credit for this library goes to https://github.com/guelfey.

---

### Overview (`vendor/github.com/moby/sys/capability/README.md`)

This is a fork of (apparently no longer maintained)
https://github.com/syndtr/gocapability package. It provides basic primitives to
work with [Linux capabilities][capabilities(7)].

For changes, see [CHANGELOG.md](./CHANGELOG.md).

[](https://pkg.go.dev/github.com/moby/sys/capability)

## Alternatives

 * https://pkg.go.dev/kernel.org/pub/linux/libs/security/libcap/cap

[capabilities(7)]: https://man7.org/linux/man-pages/man7/capabilities.7.html

---

### Overview (`vendor/github.com/urfave/cli/v3/README.md`)

# Welcome to urfave/cli

[![Go Reference][goreference_badge]][goreference_link]
[![Go Report Card][goreportcard_badge]][goreportcard_link]
[![codecov][codecov_badge]][codecov_link]
[![Tests status][test_badge]][test_link]

urfave/cli is a **declarative**, simple, fast, and fun package for building
command line tools in Go featuring:

- commands and subcommands with alias and prefix match support
- flexible and permissive help system
- dynamic shell completion for `bash`, `zsh`, `fish`, and `powershell`
- no dependencies except Go standard library
- input flags for simple types, slices of simple types, time, duration, and
  others
- compound short flag support (`-a` `-b` `-c` can be shortened to `-abc`)
- documentation generation in `man` and Markdown (supported via the
  [`urfave/cli-docs`][urfave/cli-docs] module)
- input lookup from:
  - environment variables
  - plain text files
  - structured file formats (supported via the
    [`urfave/cli-altsrc`][urfave/cli-altsrc] module)

## Documentation

See the hosted documentation website at <https://cli.urfave.org>. Contents of
this website are built from the [`./docs`](./docs) directory.

## Build tags

You can use the following build tags:

### `urfave_cli_no_template`

When set, the default help and fish completion are rendered without using
`text/template`, which makes the Go linker disable dead code elimination (see
[Binary Size](https://cli.urfave.org/v3/binary-size/#urfave_cli_no_template)).
The output is the same, but help templates can not be customized:

- `RootCommandHelpTemplate`, `CommandHelpTemplate`, `SubcommandHelpTemplate`
  and `FishCompletionTemplate` are constants;
- if the default help printer is used with a custom template (such as
  `CustomRootCommandHelpTemplate` or `CustomHelpTemplate`), it panics;
- custom template functions other than `wrap` and `wrapAt` are ignored.

Replacing `cli.HelpPrinter` works as usual, except it receives `"root"`,
`"command"` or `"subcommand"` as `templ` instead of the default template text
(a custom template is passed as is).

## Support

Check the [Q&A discussions]. If you don't find answer to your question, [create
a new discussion].

If you found a bug or have a feature request, [create a new issue].

Please keep in mind that this project is run by unpaid volunteers.

### License

See [`LICENSE`](./LICENSE).

[test_badge]: https://github.com/urfave/cli/actions/workflows/test.yml/badge.svg
[test_link]: https://github.com/urfave/cli/actions/workflows/test.yml
[goreference_badge]: https://pkg.go.dev/badge/github.com/urfave/cli/v3.svg
[goreference_link]: https://pkg.go.dev/github.com/urfave/cli/v3
[goreportcard_badge]: https://goreportcard.com/badge/github.com/urfave/cli/v3
[goreportcard_link]: https://goreportcard.com/report/github.com/urfave/cli/v3
[codecov_badge]: https://codecov.io/gh/urfave/cli/branch/main/graph/badge.svg?token=t9YGWLh05g
[codecov_link]: https://codecov.io/gh/urfave/cli
[Q&A discussions]: https://github.com/urfave/cli/discussions/categories/q-a
[create a new discussion]: https://github.com/urfave/cli/discussions/new?category=q-a
[urfave/cli-docs]: https://github.com/urfave/cli-docs
[urfave/cli-altsrc]: https://github.com/urfave/cli-altsrc
[create a new issue]: https://github.com/urfave/cli/issues/new/choose

---

### Overview (`vendor/golang.org/x/sys/unix/README.md`)

# Building `sys/unix`

The sys/unix package provides access to the raw system call interface of the
underlying operating system. See: https://godoc.org/golang.org/x/sys/unix

Porting Go to a new architecture/OS combination or adding syscalls, types, or
constants to an existing architecture/OS pair requires some manual effort;
however, there are tools that automate much of the process.

## Build Systems

There are currently two ways we generate the necessary files. We are currently
migrating the build system to use containers so the builds are reproducible.
This is being done on an OS-by-OS basis. Please update this documentation as
components of the build system change.

### Old Build System (currently for `GOOS != "linux"`)

The old build system generates the Go files based on the C header files
present on your system. This means that files
for a given GOOS/GOARCH pair must be generated on a system with that OS and
architecture. This also means that the generated code can differ from system
to system, based on differences in the header files.

To avoid this, if you are using the old build system, only generate the Go
files on an installation with unmodified header files. It is also important to
keep track of which version of the OS the files were generated from (ex.
Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
and have each OS upgrade correspond to a single change.

To build the files for your current OS and architecture, make sure GOOS and
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
your specific system. Running `mkall.sh -n` shows the commands that will be run.

Requirements: bash, go

### New Build System (currently for `GOOS == "linux"`)

The new build system uses a Docker container to generate the go files directly
from source checkouts of the kernel and various system libraries. This means
that on any platform that supports Docker, all the files using the new build
system can be generated at once, and generated files will not change based on
what the person running the scripts has installed on their computer.

The OS specific files for the new build system are located in the `${GOOS}`
directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
the kernel or system library updates, modify the Dockerfile at
`${GOOS}/Dockerfile` to checkout the new release of the source.

To build all the files under the new build system, you must be on an amd64/Linux
system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
system. Running `mkall.sh -n` shows the commands that will be run.

Requirements: bash, go, docker

## Component files

This section describes the various files used in the code generation process.
It also contains instructions on how to modify these files to add a new
architecture/OS or to add additional syscalls, types, or constants. Note that
if you are using the new build system, the scripts/programs cannot be called normally.
They must be called from within the docker container.

### asm files

The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
call dispatch. There are three entry points:
```
  func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
  func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
  func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
```
The first and second are the standard ones; they differ only in how many
arguments can be passed to the kernel. The third is for low-level use by the
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
let it know that a system call is running.

When porting Go to a new architecture/OS, this file must be implemented for
each GOOS/GOARCH pair.

### mksysnum

Mksysnum is a Go program located at `${GOOS}/mksysnum.go` (or `mksysnum_${GOOS}.go`
for the old system). This program takes in a list of header files containing the
syscall number declarations and parses them to produce the corresponding list of
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
constants.

Adding new syscall numbers is mostly done by running the build on a sufficiently
new installation of the target OS (or updating the source checkouts for the
new build system). However, depending on the OS, you may need to update the
parsing in mksysnum.

### mksyscall.go

The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
hand-written Go files which implement system calls (for unix, the specific OS,
or the specific OS/Architecture pair respectively) that need special handling
and list `//sys` comments giving prototypes for ones that can be generated.

The mksyscall.go program takes the `//sys` and `//sysnb` comments and converts
them into syscalls. This requires the name of the prototype in the comment to
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
prototype can be exported (capitalized) or not.

Adding a new syscall often just requires adding a new `//sys` function prototype
with the desired arguments and a capitalized name so it is exported. However, if
you want the interface to the syscall to be different, often one will make an
unexported `//sys` prototype, and then write a custom wrapper in
`syscall_${GOOS}.go`.

### types files

For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
`types_${GOOS}.go` on the old system). This file includes standard C headers and
creates Go type aliases to the corresponding C types. The file is then fed
through godef to get the Go compatible definitions. Finally, the generated code
is fed though mkpost.go to format the code correctly and remove any hidden or
private identifiers. This cleaned-up code is written to
`ztypes_${GOOS}_${GOARCH}.go`.

The hardest part about preparing this file is figuring out which headers to
include and which symbols need to be `#define`d to get the actual data
structures that pass through to the kernel system calls. Some C libraries
preset alternate versions for binary compatibility and translate them on the
way in and out of system calls, but there is almost always a `#define` that can
get the real ones.
See `types_darwin.go` and `linux/types.go` for examples.

To add a new type, add in the necessary include statement at the top of the
file (if it is not already there) and add in a type alias line. Note that if
your type is significantly different on different architectures, you may need
some `#if/#elif` macros in your include statements.

### mkerrors.sh

This script is used to generate the system's various constants. This doesn't
just include the error numbers and error strings, but also the signal numbers
and a wide variety of miscellaneous constants. The constants come from the list
of include files in the `includes_${uname}` variable. A regex then picks out
the desired `#define` statements, and generates the corresponding Go constants.
The error numbers and strings are generated from `#include <errno.h>`, and the
signal numbers and strings are generated from `#include <signal.h>`. All of
these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
`_errors.c`, which prints out all the constants.

To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants.

### internal/mkmerge

This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these
into a common file for each OS.

The merge is performed in the following steps:
1. Construct the set of common code that is identical in all architecture-specific files.
2. Write this common code to the merged file.
3. Remove the common code from all architecture-specific files.


## Generated files

### `zerrors_${GOOS}_${GOARCH}.go`

A file containing all of the system's generated error numbers, error strings,
signal numbers, and constants. Generated by `mkerrors.sh` (see above).

### `zsyscall_${GOOS}_${GOARCH}.go`

A file containing all the generated syscalls for a specific GOOS and GOARCH.
Generated by `mksyscall.go` (see above).

### `zsysnum_${GOOS}_${GOARCH}.go`

A list of numeric constants for all the syscall number of the specific GOOS
and GOARCH. Generated by mksysnum (see above).

### `ztypes_${GOOS}_${GOARCH}.go`

A file containing Go types for passing into (or returning from) syscalls.
Generated by godefs and the types file (see above).

---

### Overview (`vendor/github.com/opencontainers/selinux/pkg/pwalkdir/README.md`)

## pwalkdir: parallel implementation of filepath.WalkDir

This is a wrapper for [filepath.WalkDir](https://pkg.go.dev/path/filepath#WalkDir)
which may speed it up by calling multiple callback functions (WalkDirFunc)
in parallel, utilizing goroutines.

By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
This can be changed by using WalkN function which has the additional
parameter, specifying the number of goroutines (concurrency).

### pwalk vs pwalkdir

This package is very similar to
[pwalk](https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir),
but utilizes `filepath.WalkDir` (added to Go 1.16), which does not call stat(2)
on every entry and is therefore faster (up to 3x, depending on usage scenario).

Users who are OK with requiring Go 1.16+ should switch to this
implementation.

### Caveats

Please note the following limitations of this code:

* Unlike filepath.WalkDir, the order of calls is non-deterministic;

* Only primitive error handling is supported:

  * fs.SkipDir is not supported;

  * ErrNotExist errors from filepath.WalkDir are silently ignored for any path
    except the top directory (WalkDir argument); any other error is returned to
    the caller of WalkDir;

  * once any error is returned from any walkDirFunc instance, no more calls
    to WalkDirFunc are made, and the error is returned to the caller of WalkDir;

  * if more than one WalkDirFunc instance will return an error, only one
    of such errors will be propagated to and returned by WalkDir, others
    will be silently discarded.

### Documentation

For the official documentation, see
https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalkdir

### Benchmarks

For a WalkDirFunc that consists solely of the return statement, this
implementation is about 15% slower than the standard library's
filepath.WalkDir.

Otherwise (if a WalkDirFunc is actually doing something) this is usually
faster, except when the WalkDirN(..., 1) is used. Run `go test -bench .`
to see how different operations can benefit from it, as well as how the
level of parallelism affects the speed.

---

### Overview (`vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/README.md`)

## gocompat ##

This directory contains backports of stdlib functions from later Go versions so
the filepath-securejoin can continue to be used by projects that are stuck with
Go 1.18 support. Note that often filepath-securejoin is added in security
patches for old releases, so avoiding the need to bump Go compiler requirements
is a huge plus to downstreams.

The source code is licensed under the same license as the Go stdlib. See the
source files for the precise license information.

---

### Cgroup V2 (`docs/cgroup-v2.md`)

# cgroup v2

runc fully supports cgroup v2 (unified mode) since v1.0.0-rc93.

To use cgroup v2, you might need to change the configuration of the host init system.
The following distributions are known to use cgroup v2 by default:

- Fedora (since 31)
- Arch Linux (since April 2021)
- openSUSE Tumbleweed (since c. 2021)
- Debian GNU/Linux (since 11)
- Ubuntu (since 21.10)
- RHEL and RHEL-like distributions (since 9)

On other systemd-based distros, cgroup v2 can be enabled by adding `systemd.unified_cgroup_hierarchy=1` to the kernel cmdline.

## Am I using cgroup v2?

Yes if `/sys/fs/cgroup/cgroup.controllers` is present.

## Host Requirements
### Kernel
* Recommended version: 5.2 or later
* Minimum version: 4.15

Kernel older than 5.2 is not recommended due to lack of freezer.

Notably, kernel older than 4.15 MUST NOT be used (unless you are running containers with user namespaces), as it lacks support for controlling permissions of devices.

### Systemd
On cgroup v2 hosts, it is highly recommended to run runc with the systemd cgroup driver (`runc --systemd-cgroup`), though not mandatory.

The recommended systemd version is 244 or later. Older systemd does not support delegation of `cpuset` controller.

Make sure you also have the `dbus-user-session` (Debian/Ubuntu) or `dbus-daemon` (CentOS/Fedora) package installed, and that `dbus` is running. On Debian-flavored distros, this can be accomplished like so:

```bash
sudo apt install -y dbus-user-session
systemctl --user start dbus
```

## Rootless
On cgroup v2 hosts, rootless runc can talk to systemd to get cgroup permissions to be delegated.

```bash
runc spec --rootless
jq '.linux.cgroupsPath="user.slice:runc:foo"' config.json | sponge config.json
runc --systemd-cgroup run foo
```

The container processes are executed in a cgroup like `/user.slice/user-$(id -u).slice/user@$(id -u).service/user.slice/runc-foo.scope`.

### Configuring delegation
Typically, only `memory` and `pids` controllers are delegated to non-root users by default.

```console
$ cat /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers
memory pids
```

To allow delegation of other controllers, you need to change the systemd configuration as follows:

```bash
sudo mkdir -p /etc/systemd/system/user@.service.d
cat <<EOF | sudo tee /etc/systemd/system/user@.service.d/delegate.conf
[Service]
Delegate=cpu cpuset io memory pids
EOF
sudo systemctl daemon-reload
```

---

### Checkpoint Restore (`docs/checkpoint-restore.md`)

# Checkpoint and Restore #

For a basic description about checkpointing and restoring containers with
`runc` please see [runc-checkpoint(8)](../man/runc-checkpoint.8.md) and
[runc-restore(8)](../man/runc-restore.8.md).

## Checkpoint/Restore Annotations ##

In addition to specifying options on the command-line like it is described
in the man-pages (see above), it is also possible to influence CRIU's
behaviour using CRIU configuration files. For details about CRIU's
configuration file support please see [CRIU's wiki](https://criu.org/Configuration_files).

In addition to CRIU's default configuration files `runc` tells CRIU to
also evaluate the file `/etc/criu/runc.conf`. Using the annotation
`org.criu.config` it is, however, possible to change this additional
CRIU configuration file.

If the annotation `org.criu.config` is set to an empty string `runc`
will not pass any additional configuration file to CRIU. With an empty
string it is therefore possible to disable the additional CRIU configuration
file. This can be used to make sure that no additional configuration file
changes CRIU's behaviour accidentally.

If the annotation `org.criu.config` is set to a non-empty string `runc` will
pass that string to CRIU to be evaluated as an additional configuration file.
If CRIU cannot open this additional configuration file, it will ignore this
file and continue.

### Annotation Example to disable additional CRIU configuration file ###

```
{
	"ociVersion": "1.0.0",
	"annotations": {
		"org.criu.config": ""
	},
	"process": {
```

### Annotation Example to set a specific CRIU configuration file ###

```
{
	"ociVersion": "1.0.0",
	"annotations": {
		"org.criu.config": "/etc/special-runc-criu-options"
	},
	"process": {
```

---

### Deprecated (`docs/deprecated.md`)

# Deprecated features

The following features are deprecated:

Feature                                  | Deprecation  release | Removal release
---------------------------------------- | -------------------- | ------------------
cgroup v1                                | v1.4.0               | (May 2029)



- The latest release in May 2029 may not necessarily support cgroup v1, but there will be at least one maintained branch with the support for cgroup v1.

---

### Experimental (`docs/experimental.md`)

# Experimental features

The following features were experimental in the past:

Feature                                  | Experimental release | Graduation release
---------------------------------------- | -------------------- | ------------------
cgroup v2                                | v1.0.0-rc91          | v1.0.0-rc93
The `runc features` command              | v1.1.0               | v1.2.0
runc-dmz                                 | v1.2.0-rc1           | Dropped in v1.2.1

---

### Spec Conformance (`docs/spec-conformance.md`)

# Spec conformance

This branch of runc implements the [OCI Runtime Spec v1.3.0](https://github.com/opencontainers/runtime-spec/tree/v1.3.0)
for the `linux` platform.

## Deviations

runc deviates from the spec in the following ways:

* [`ociVersion`](https://github.com/opencontainers/runtime-spec/blob/v1.3.0/config.md#specification-version)
  is not validated: runc does not generate an error if it is missing, empty, not
  in SemVer format, or specifies a version not supported by runc (e.g. with a
  different major version).
* If [`umask`](https://github.com/opencontainers/runtime-spec/blob/v1.3.0/config.md#user)
  is not specified, the umask of the container init process is set to `0022`,
  rather than left unchanged from the calling process' umask. For `runc exec`,
  the umask is left unchanged.

## Architectures

The following architectures are supported:

runc binary  | seccomp
-------------|-------------------------------------------------------
`amd64`      | `SCMP_ARCH_X86`, `SCMP_ARCH_X86_64`, `SCMP_ARCH_X32`
`arm64`      | `SCMP_ARCH_ARM`, `SCMP_ARCH_AARCH64`
`armel`      | `SCMP_ARCH_ARM`
`armhf`      | `SCMP_ARCH_ARM`
`ppc64le`    | `SCMP_ARCH_PPC64LE`
`riscv64`    | `SCMP_ARCH_RISCV64`
`s390x`      | `SCMP_ARCH_S390`, `SCMP_ARCH_S390X`
`loong64`    | `SCMP_ARCH_LOONGARCH64`

The runc binary might be compilable for i386, big-endian PPC64,
and several MIPS variants too, but these architectures are not officially supported.

---

### Systemd (`docs/systemd.md`)

## systemd cgroup driver

By default, runc creates cgroups and sets cgroup limits on its own (this mode
is known as fs cgroup driver). When `--systemd-cgroup` global option is given
(as in e.g. `runc --systemd-cgroup run ...`), runc switches to systemd cgroup
driver. This document describes its features and peculiarities.

### systemd unit name and placement

When creating a container, runc requests systemd (over dbus) to create
a transient unit for the container, and place it into a specified slice.

The name of the unit and the containing slice is derived from the container
runtime spec in the following way:

1. If `Linux.CgroupsPath` is set, it is expected to be in the form
   `[slice]:[prefix]:[name]`.

   Here `slice` is a systemd slice under which the container is placed.
   If empty, it defaults to `system.slice`, except when cgroup v2 is
   used and rootless container is created, in which case it defaults
   to `user.slice`.

   Note that `slice` can contain dashes to denote a sub-slice
   (e.g. `user-1000.slice` is a correct notation, meaning a subslice
   of `user.slice`), but it must not contain slashes (e.g.
   `user.slice/user-1000.slice` is invalid).

   A `slice` of `-` represents a root slice.

   Next, `prefix` and `name` are used to compose the  unit name, which
   is `<prefix>-<name>.scope`, unless `name` has `.slice` suffix, in
   which case `prefix` is ignored and the `name` is used as is.
   The default value for both `prefix` and `name` is empty string.

2. If `Linux.CgroupsPath` is not set or empty, it works the same way as if it
   would be set to `:runc:<container-id>`. See the description above to see
   what it transforms to.

As described above, a unit being created can either be a scope or a slice.
For a scope, runc specifies its parent slice via a _Slice=_ systemd property,
and also sets _Delegate=true_. For a slice, runc specifies a weak dependency on
the parent slice via a _Wants=_ property.

### Resource limits

runc always enables accounting for all controllers, regardless of any limits
being set. This means it unconditionally sets the following properties for the
systemd unit being created:

 * _CPUAccounting=true_
 * _IOAccounting=true_ (_BlockIOAccounting_ for cgroup v1)
 * _MemoryAccounting=true_
 * _TasksAccounting=true_

The resource limits of the systemd unit are set by runc by translating the
runtime spec resources to systemd unit properties.

Such translation is by no means complete, as there are some cgroup properties
that can not be set via systemd.  Therefore, runc systemd cgroup driver is
backed by fs driver (in other words, cgroup limits are first set via systemd
unit properties, and when by writing to cgroupfs files).

The set of runtime spec resources which is translated by runc to systemd unit
properties depends on kernel cgroup version being used (v1 or v2), and on the
systemd version being run. If an older systemd version (which does not support
some resources) is used, runc do not set those resources.

The following tables summarize which properties are translated.

#### cgroup v1

| runtime spec resource | systemd property name | min systemd version |
|-----------------------|-----------------------|---------------------|
| memory.limit          | MemoryLimit           |                     |
| cpu.shares            | CPUShares             |                     |
| blockIO.weight        | BlockIOWeight         |                     |
| pids.limit            | TasksMax              |                     |
| cpu.cpus              | AllowedCPUs           | v244                |
| cpu.mems              | AllowedMemoryNodes    | v244                |

#### cgroup v2

| runtime spec resource   | systemd property name | min systemd version |
|-------------------------|-----------------------|---------------------|
| memory.limit            | MemoryMax             |                     |
| memory.reservation      | MemoryLow             |                     |
| memory.swap             | MemorySwapMax         |                     |
| cpu.shares              | CPUWeight             |                     |
| pids.limit              | TasksMax              |                     |
| cpu.cpus                | AllowedCPUs           | v244                |
| cpu.mems                | AllowedMemoryNodes    | v244                |
| unified.cpu.max         | CPUQuota, CPUQuotaPeriodSec | v242          |
| unified.cpu.weight      | CPUWeight             |                     |
| unified.cpu.idle        | CPUWeight             | v252                |
| unified.cpuset.cpus     | AllowedCPUs           | v244                |
| unified.cpuset.mems     | AllowedMemoryNodes    | v244                |
| unified.memory.high     | MemoryHigh            |                     |
| unified.memory.low      | MemoryLow             |                     |
| unified.memory.min      | MemoryMin             |                     |
| unified.memory.max      | MemoryMax             |                     |
| unified.memory.swap.max | MemorySwapMax         |                     |
| unified.pids.max        | TasksMax              |                     |

For documentation on systemd unit resource properties, see
`systemd.resource-control(5)` man page.

### Auxiliary properties

Auxiliary properties of a systemd unit (as shown by `systemctl show
<unit-name>` after the container is created) can be set (or overwritten) by
adding annotations to the container runtime spec (`config.json`).

For example:

```json
        "annotations": {
                "org.systemd.property.TimeoutStopUSec": "uint64 123456789",
                "org.systemd.property.CollectMode":"'inactive-or-failed'"
        },
```

The above will set the following properties:

* `TimeoutStopSec` to 2 minutes and 3 seconds;
* `CollectMode` to "inactive-or-failed".

The values must be in the gvariant text format, as described in
[gvariant documentation](https://docs.gtk.org/glib/gvariant-text-format.html).

To find out which type systemd expects for a particular parameter, please
consult systemd sources.

---

### Terminals (`docs/terminals.md`)

# Terminals and Standard IO #

*Note that the default configuration of `runc` (foreground, new terminal) is
generally the best option for most users. This document exists to help explain
what the purpose of the different modes is, and to try to steer users away from
common mistakes and misunderstandings.*

In general, most processes on Unix (and Unix-like) operating systems have 3
standard file descriptors provided at the start, collectively referred to as
"standard IO" (`stdio`):

* `0`: standard-in (`stdin`), the input stream into the process
* `1`: standard-out (`stdout`), the output stream from the process
* `2`: standard-error (`stderr`), the error stream from the process

When creating and running a container via `runc`, it is important to take care
to structure the `stdio` the new container's process receives. In some ways
containers are just regular processes, while in other ways they're an isolated
sub-partition of your machine (in a similar sense to a VM). This means that the
structure of IO is not as simple as with ordinary programs (which generally
just use the file descriptors you give them).

## Other File Descriptors ##

Before we continue, it is important to note that processes can have more file
descriptors than just `stdio`. By default in `runc` no other file descriptors
will be passed to the spawned container process. If you wish to explicitly pass
file descriptors to the container you have to use the `--preserve-fds` option.
These ancillary file descriptors don't have any of the strange semantics
discussed further in this document (those only apply to `stdio`) -- they are
passed untouched by `runc`.

It should be noted that `--preserve-fds` does not take individual file
descriptors to preserve. Instead, it takes how many file descriptors (not
including `stdio` or `LISTEN_FDS`) should be passed to the container. In the
following example:

```bash
runc run --preserve-fds 5 <container>
```

`runc` will pass the first `5` file descriptors (`3`, `4`, `5`, `6`, and `7` --
assuming that `LISTEN_FDS` has not been configured) to the container.

In addition to `--preserve-fds`, `LISTEN_FDS` file descriptors are passed
automatically to allow for `systemd`-style socket activation. To extend the
above example:

```bash
LISTEN_PID=$pid_of_runc LISTEN_FDS=3 runc run --preserve-fds 5 <container>
```

`runc` will now pass the first `8` file descriptors (and it will also pass
`LISTEN_FDS=3` and `LISTEN_PID=1` to the container). The first `3` (`3`, `4`,
and `5`) were passed due to `LISTEN_FDS` and the other `5` (`6`, `7`, `8`, `9`,
and `10`) were passed due to `--preserve-fds`. You should keep this in mind if
you use `runc` directly in something like a `systemd` unit file. To disable
this `LISTEN_FDS`-style passing just unset `LISTEN_FDS`.

**Be very careful when passing file descriptors to a container process.** Due
to some Linux kernel (mis)features, a container with access to certain types of
file descriptors (such as `O_PATH` descriptors) outside of the container's root
file system can use these to break out of the container's pivoted mount
namespace. [This has resulted in CVEs in the past.][CVE-2016-9962]

[CVE-2016-9962]: https://nvd.nist.gov/vuln/detail/CVE-2016-9962

## <a name="terminal-modes" /> Terminal Modes ##

`runc` supports two distinct methods for passing `stdio` to the container's
primary process:

* [new terminal](#new-terminal) (`terminal: true`)
* [pass-through](#pass-through) (`terminal: false`)

When first using `runc` these two modes will look incredibly similar, but this
can be quite deceptive as these different modes have quite different
characteristics.

By default, `runc spec` will create a configuration that will create a new
terminal (`terminal: true`). However, if the `terminal: ...` line is not
present in `config.json` then pass-through is the default.

*In general we recommend using new terminal, because it means that tools like
`sudo` will work inside your container. But pass-through can be useful if you
know what you're doing, or if you're using `runc` as part of a non-interactive
pipeline.*

### <a name="new-terminal"> New Terminal ###

In new terminal mode, `runc` will create a brand-new "console" (or more
precisely, a new pseudo-terminal using the container's namespaced
`/dev/pts/ptmx`) for your contained process to use as its `stdio`.

When you start a process in new terminal mode, `runc` will do the following:

1. Create a new pseudo-terminal.
2. Pass the slave end to the container's primary process as its `stdio`.
3. Send the master end to a process to interact with the `stdio` for the
   container's primary process ([details below](#runc-modes)).

It should be noted that since a new pseudo-terminal is being used for
communication with the container, some strange properties of pseudo-terminals
might surprise you. For instance, by default, all new pseudo-terminals
translate the byte `'\n'` to the sequence `'\r\n'` on both `stdout` and
`stderr`. In addition there are [a whole range of `ioctls(2)` that can only
interact with pseudo-terminal `stdio`][tty_ioctl(4)].

> **NOTE**: In new terminal mode, all three `stdio` file descriptors are the
> same underlying file. The reason for this is to match how a shell's `stdio`
> looks to a process (as well as remove race condition issues with having to
> deal with multiple master pseudo-terminal file descriptors). However this
> means that it is not really possible to uniquely distinguish between `stdout`
> and `stderr` from the caller's perspective.

#### Issues

If you see an error like

```
open /dev/tty: no such device or address
```

from runc, it means it can't open a terminal (because there isn't one). This
can happen when stdin (and possibly also stdout and stderr) are redirected,
or in some environments that lack a tty (such as GitHub Actions runners).

The solution to this is to *not* use a terminal for the container, i.e. have
`terminal: false` in `config.json`. If the container really needs a terminal
(some programs require one), you can provide one, using one of the following
methods.

One way is to use `ssh` with the `-tt` flag. The second `t` forces a terminal
allocation even if there's no local one -- and so it is required when stdin is
not a terminal (some `ssh` implementations only look for a terminal on stdin).

Another way is to run runc under the `script` utility, like this

```bash
script -e -c 'runc run <container>'
```

[tty_ioctl(4)]: https://linux.die.net/man/4/tty_ioctl

### <a name="pass-through"> Pass-Through ###

If you have already set up some file handles that you wish your contained
process to use as its `stdio`, then you can ask `runc` to pass them through to
the contained process (this is not necessarily the same as `--preserve-fds`'s
passing of file descriptors -- [details below](#runc-modes)). As an example
(assuming that `terminal: false` is set in `config.json`):

```bash
echo input | runc run some_container > /tmp/log.out 2> /tmp/log.err
```

Here the container's various `stdio` file descriptors will be substituted with
the following:

* `stdin` will be sourced from the `echo input` pipeline.
* `stdout` will be output into `/tmp/log.out` on the host.
* `stderr` will be output into `/tmp/log.err` on the host.

It should be noted that the actual file handles seen inside the container may
be different [based on the mode `runc` is being used in](#runc-modes) (for
instance, the file referenced by `1` could be `/tmp/log.out` directly or a pipe
which `runc` is using to buffer output, based on the mode). However the net
result will be the same in either case. In principle you could use the [new
terminal mode](#new-terminal) in a pipeline, but the difference will become
more clear when you are introduced to [`runc`'s detached mode](#runc-modes).

## <a name="runc-modes" /> `runc` Modes ##

`runc` itself runs in two modes:

* [foreground](#foreground)
* [detached](#detached)

You can use either [terminal mode](#terminal-modes) with either `runc` mode.
However, there are considerations that may indicate preference for one mode
over another. It should be noted that while two types of modes (terminal and
`runc`) are conceptually independent from each other, you should be aware of
the intricacies of which combination you are using.

*In general we recommend using foreground because it's the most
straight-forward to use, with the only downside being that you will have a
long-running `runc` process. Detached mode is difficult to get right and
generally requires having your own `stdio` management.*

### Foreground ###

The default (and most straight-forward) mode of `runc`. In this mode, your
`runc` command remains in the foreground with the container process as a child.
All `stdio` is buffered through the foreground `runc` process (irrespective of
which terminal mode you are using). This is conceptually quite similar to
running a normal process interactively in a shell (and if you are using `runc`
in a shell interactively, this is what you should use).

Because the `stdio` will be buffered in this mode, some very important
peculiarities of this mode should be kept in mind:

* With [new terminal mode](#new-terminal), the container will see a
  pseudo-terminal as its `stdio` (as you might expect). However, the `stdio` of
  the foreground `runc` process will remain the `stdio` that the process was
  started with -- and `runc` will copy all `stdio` between its `stdio` and the
  container's `stdio`. This means that while a new pseudo-terminal has been
  created, the foreground `runc` process manages it over the lifetime of the
  container.

* With [pass-through mode](#pass-through), the foreground `runc`'s `stdio` is
  **not** passed to the container. Instead, the container's `stdio` is a set of
  pipes which are used to copy data between `runc`'s `stdio` and the
  container's `stdio`. This means that the container never has direct access to
  host file descriptors (aside from the pipes created by the container runtime,
  but that shouldn't be an issue).

The main drawback of the foreground mode of operation is that it requires a
long-running foreground `runc` process. If you kill the foreground `runc`
process then you will no longer have access to the `stdio` of the container
(and in most cases this will result in the container dying abnormally due to
`SIGPIPE` or some other error). By extension this means that any bug in the
long-running foreground `runc` process (such as a memory leak) or a stray
OOM-kill sweep could result in your container being killed **through no fault
of the user**. In addition, there is no way in foreground mode of passing a
file descriptor directly to the container process as its `stdio` (like
`--preserve-fds` does).

These shortcomings are obviously sub-optimal and are the reason that `runc` has
an additional mode called "detached mode".

### Detached ###

In contrast to foreground mode, in detached mode there is no long-running
foreground `runc` process once the container has started. In fact, there is no
long-running `runc` process at all. However, this means that it is up to the
caller to handle the `stdio` after `runc` has set it up for you. In a shell
this means that the `runc` command will exit and control will return to the
shell, after the container has been set up.

You can run `runc` in detached mode in one of the following ways:

* `runc run -d ...` which operates similar to `runc run` but is detached.
* `runc create` followed by `runc start` which is the standard container
  lifecycle defined by the OCI runtime specification (`runc create` sets up the
  container completely, waiting for `runc start` to begin execution of user
  code).

The main use-case of detached mode is for higher-level tools that want to be
wrappers around `runc`. By running `runc` in detached mode, those tools have
far more control over the container's `stdio` without `runc` getting in the
way (most wrappers around `runc` like `cri-o` or `containerd` use detached mode
for this reason).

Unfortunately using detached mode is a bit more complicated and requires more
care than the foreground mode -- mainly because it is now up to the caller to
handle the `stdio` of the container.

Another complication is that the parent process is responsible for acting as
the subreaper for the container. In short, you need to call
`prctl(PR_SET_CHILD_SUBREAPER, 1, ...)` in the parent process and correctly
handle the implications of being a subreaper. Failing to do so may result in
zombie processes being accumulated on your host.

These tasks are usually performed by a dedicated (and minimal) monitor process
per-container. For the sake of comparison, other runtimes such as LXC do not
have an equivalent detached mode and instead integrate this monitor process
into the container runtime itself -- this has several tradeoffs, and runc has
opted to support delegating the monitoring responsibility to the parent process
through this detached mode.

#### Detached Pass-Through ####

In detached mode, pass-through actually does what it says on the tin -- the
`stdio` file descriptors of the `runc` process are passed through (untouched)
to the container's `stdio`. The purpose of this option is to allow a user to
set up `stdio` for a container themselves and then force `runc` to just use
their pre-prepared `stdio` (without any pseudo-terminal funny business). *If
you don't see why this would be useful, don't use this option.*

**You must be incredibly careful when using detached pass-through (especially
in a shell).** The reason for this is that by using detached pass-through you
are passing host file descriptors to the container. In the case of a shell,
usually your `stdio` is going to be a pseudo-terminal (on your host). A
malicious container could take advantage of TTY-specific `ioctls` like
`TIOCSTI` to fake input into the **host** shell (remember that in detached
mode, control is returned to your shell and so the terminal you've given the
container is being read by a shell prompt).

There are also several other issues with running non-malicious containers in a
shell with detached pass-through (where you pass your shell's `stdio` to the
container):

* Output from the container will be interleaved with output from your shell (in
  a non-deterministic way), without any real way of distinguishing from where a
  particular piece of output came from.

* Any input to `stdin` will be non-deterministically split and given to either
  the container or the shell (because both are blocked on a `read(2)` of the
  same FIFO-style file descriptor).

They are all related to the fact that there is going to be a race when either
your host or the container tries to read from (or write to) `stdio`. This
problem is especially obvious when in a shell, where usually the terminal has
been put into raw mode (where each individual key-press should cause `read(2)`
to return).

> **NOTE**: There is also currently a [known problem][issue-1721] where using
> detached pass-through will result in the container hanging if the `stdout` or
> `stderr` is a pipe (though this should be a temporary issue).

[issue-1721]: https://github.com/opencontainers/runc/issues/1721

#### Detached New Terminal ####

When creating a new pseudo-terminal in detached mode, and fairly obvious
problem appears -- how do we use the new terminal that `runc` created? Unlike
in pass-through, `runc` has created a new set of file descriptors that need to
be used by *something* in order for container communication to work.

The way this problem is resolved is through the use of Unix domain sockets.
There is a feature of Unix sockets called `SCM_RIGHTS` which allows a file
descriptor to be sent through a Unix socket to a completely separate process
(which can then use that file descriptor as though they opened it). When using
`runc` in detached new terminal mode, this is how a user gets access to the
pseudo-terminal's master file descriptor.

To this end, there is a new option (which is required if you want to use `runc`
in detached new terminal mode): `--console-socket`. This option takes the path
to a Unix domain socket which `runc` will connect to and send the
pseudo-terminal master file descriptor down. The general process for getting
the pseudo-terminal master is as follows:

1. Create a Unix domain socket at some path, `$socket_path`.
2. Call `runc run` or `runc create` with the argument `--console-socket
   $socket_path`.
3. Using `recvmsg(2)` retrieve the file descriptor sent using `SCM_RIGHTS` by
   `runc`.
4. Now the manager can interact with the `stdio` of the container, using the
   retrieved pseudo-terminal master.

After `runc` exits, the only process with a copy of the pseudo-terminal master
file descriptor is whoever read the file descriptor from the socket.

> **NOTE**: Currently `runc` doesn't support abstract socket addresses (due to
> it not being possible to pass an `argv` with a null-byte as the first
> character). In the future this may change, but currently you must use a valid
> path name.

In order to help users make use of detached new terminal mode, we have provided
a [Go implementation in the `go-runc` bindings][containerd/go-runc.Socket], as
well as [a simple client][recvtty].

[containerd/go-runc.Socket]: https://godoc.org/github.com/containerd/go-runc#Socket
[recvtty]: /tests/cmd/recvtty

---

--- METRICS ---
- Files Extracted: 32
- Estimated Token Budget: ~30893 tokens
- Canonical Reference: https://codewiki.google/github.com/opencontainers/runc
