Skip to content
This repository has been archived by the owner on Oct 9, 2020. It is now read-only.

rootless OCI container runtime with ptrace hacks (No root privileges nor SUID binaries (e.g. newuidmap) are required!)

License

Notifications You must be signed in to change notification settings

rootless-containers/runrootless

Repository files navigation

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 ( opencontainers/runc#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

  • apt / dpkg may crash when seccomp acceleration is enabled: #4

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...

About

rootless OCI container runtime with ptrace hacks (No root privileges nor SUID binaries (e.g. newuidmap) are required!)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published