• This repository has been archived on 09/Oct/2020
  • Stars
    star
    117
  • Rank 301,751 (Top 6 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created almost 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

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