rootless OCI container runtime with ptrace hacks (No root privileges nor SUID binaries (e.g. newuidmap) are required!)
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bundle runrootless: disable seccomp acceleration by default Jan 10, 2018
examples
misc
vendor
.dockerignore
.travis.yml
Dockerfile
LICENSE
README.md examples: add skopeo-umoci Apr 13, 2018
install-proot.sh
main.go
runccompat.go
runcreate.go
runcreate_test.go
vendor.conf

README.md

runROOTLESS: rootless OCI container runtime with ptrace hacks

Build Status

Quick start (No root privileges nor SUID binaries are required!)

Install

Requires: Go, runc

user$ go get github.com/rootless-containers/runrootless
user$ $GOPATH/src/github.com/rootless-containers/runrootless/install-proot.sh

Future version should install a pre-built PRoot binary automatically on the first run.

Usage

Create an example Ubuntu bundle:

user$ cd ./examples/ubuntu
user$ ./prepare.sh
user$ ls -1F
config.json
prepare.sh
rootfs/

Make sure the bundle cannot be executed with the regular runc:

user$ runc run ubuntu
rootless containers require user namespaces

Note that even with runc spec --rootless, you cannot execute apt:

user$ rm config.json
user$ runc spec --rootless
user$ sed -i 's/"readonly": true/"readonly": false/' config.json
user$ runc run ubuntu
# apt update
E: setgroups 65534 failed - setgroups (1: Operation not permitted)
E: setegid 65534 failed - setegid (22: Invalid argument)
E: seteuid 100 failed - seteuid (22: Invalid argument)
E: setgroups 0 failed - setgroups (1: Operation not permitted)
Reading package lists... Done
W: chown to _apt:root of directory /var/lib/apt/lists/partial failed - SetupAPTPartialDirectory (22: Invalid argument)
E: setgroups 65534 failed - setgroups (1: Operation not permitted)
E: setegid 65534 failed - setegid (22: Invalid argument)
E: seteuid 100 failed - seteuid (22: Invalid argument)
E: setgroups 0 failed - setgroups (1: Operation not permitted)
E: Method gave invalid 400 URI Failure message: Failed to setgroups - setgroups (1: Operation not permitted)
E: Method http has died unexpectedly!
E: Sub-process http returned an error code (112)_

With runrootless, you can execute apt successfully:

user$ ./prepare.sh
user$ runrootless run ubuntu
# apt update
# apt install -y cowsay
# /usr/games/cowsay hello rootless world
 ______________________
< hello rootless world >
 ----------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Other examples

CentOS:

user$ cd ./examples/centos
user$ ./prepare.sh
user$ runrootless run centos
sh-4.2# yum install -y epel-release
sh-4.2# yum install -y cowsay
sh-4.2# cowsay hello rootless world

Alpine Linux:

user$ cd ./examples/alpine
user$ ./prepare.sh
user$ runrootless run alpine
/ # apk update
/ # apk add fortune
/ # fortune

Arbitrary Docker image:

user$ cd ./examples/docker-image
user$ ./prepare.sh opensuse
user$ runrootless run opensuse
sh-4.3# zypper install cowsay
sh-4.3# cowsay hello rootless world

Arbitrary container image, using skopeo and umoci. umoci and runROOTLESS share emulated chown(2) information via user.rootlesscontainers xattr.

user$ cd ./examples/skopeo-umoci
user$ ./prepare.sh docker://ubuntu
user$ cd umoci-bundle
user$ runrootless run ubuntu

runROOTLESS can be also executed inside Docker container, but --privileged is still required ( https://github.com/opencontainers/runc/issues/1456 )

host$ docker run -it --rm --privileged akihirosuda/runrootless
~ $ id
uid=1000(user) gid=1000(user)
~ $ cd ~/examples/ubuntu/
~/examples/ubuntu $ ./prepare.sh
~/examples/ubuntu $ runrootless run ubuntu
#

Environment variables

  • RUNROOTLESS_SECCOMP=1: enable seccomp acceleration (unstable)

How it works

  • Transform a regular config.json to rootless one, and create a new OCI runtime bundle with it.
  • Bind-mount a static PRoot binary so as to allow apt/yum commands.
  • Inject the PRoot binary to process.args.
  • Invoke plain runC.

Known issues

Future work

OCI Runtime Hook mode

runROOTLESS could be reimplemented as a OCI Runtime Hook (prestart) that works with an arbitrary OCI Runtime. This work would need adding support for PTRACE_ATTACH to PRoot. Also, it would require YAMA to be disabled.

Reimplement PRoot in Go

This is hard than I initially thought...