Go to file
Cédric VINCENT ea2c72493f Demo: how to convert file-backed exec mmappings into anonymous mmapping + copy.
1. Initial setup:

    $ mount -o noexec /dev/mapper/cryptvg-root /mnt/hd
    $ mount | grep hd
    /dev/mapper/cryptvg-root on /mnt/hd type ext4 (rw,noexec)

2. Sanity check:

    $ /mnt/hd/bin/cat
    -bash: /mnt/hd/bin/cat: Permission denied

3. With this extension:

    $ proot -b /lib64/ld-linux-x86-64.so.2 -R /mnt/hd /bin/cat /proc/self/maps | grep xp
    00400000-0040b000 r-xp 00000000 00:00 0
    555555554000-555555577000 r-xp 00000000 fd:01 272225                     /lib64/ld-2.15.so
    7ffff7c0f000-7ffff7dc4000 r-xp 00000000 00:00 0
    7ffff7ffe000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

4. Random notes:

   * "access(path, X_OK)" must be emulated

   * the loader (mmaped by the kernel) can't be on a noexec partition

   * it's tested with a x86_64 rootfs only

   * it's not well tested, actually

   * it's slow:

     - emacs startup time: ~2s vs. ~6s
     - xterm startup time: ~0.1s vs. ~1.5s

   * it can be optimized (mmap only the text segment)
2013-08-21 12:43:52 +02:00
doc Import the article about how to migrate from ScratchBox2. 2013-08-12 14:42:31 +02:00
src Demo: how to convert file-backed exec mmappings into anonymous mmapping + copy. 2013-08-21 12:43:52 +02:00
tests Fix test-2401b850: the specific support for Valgrind was missing. 2013-07-18 16:04:01 +02:00
.travis.yml Make the test-suite more portable. 2012-10-23 17:33:08 +02:00
AUTHORS Simplify fake_id0 + fix support for chmod-like and stat-like syscalls. 2013-01-09 08:46:43 +01:00
COPYING Add a copy of PRoot's license. 2011-11-07 08:37:28 +01:00
README.rst Add a top-level link to make GitHub display the user manual. 2012-03-26 11:03:11 +02:00

README.rst

=======
 PRoot
=======

-------------------------------------------------------------------------
``chroot``, ``mount --bind``, and ``binfmt_misc`` without privilege/setup
-------------------------------------------------------------------------

:Date: 2013-07-22
:Version: 3.1
:Manual section: 1


Synopsis
========

**proot** [*option*] ... [*command*]


Description
===========

PRoot is a user-space implementation of ``chroot``, ``mount --bind``,
and ``binfmt_misc``.  This means that users don't need any privileges
or setup to do things like using an arbitrary directory as the new
root filesystem, making files accessible somewhere else in the
filesystem hierarchy, or executing programs built for another CPU
architecture transparently through QEMU user-mode.  Also, developers
can add their own features or use PRoot as a Linux process
instrumentation engine thanks to its extension mechanism.  Technically
PRoot relies on ``ptrace``, an unprivileged system-call available in
every Linux kernel.

The new root file-system, a.k.a *guest rootfs*, typically contains a
Linux distribution.  By default PRoot confines the execution of
programs to the guest rootfs only, however users can use the built-in
*mount/bind* mechanism to access files and directories from the actual
root file-system, a.k.a *host rootfs*, just as if they were part of
the guest rootfs.

When the guest Linux distribution is made for a CPU architecture
incompatible with the host one, PRoot uses the CPU emulator QEMU
user-mode to execute transparently guest programs.  It's a convenient
way to develop, to build, and to validate any guest Linux packages
seamlessly on users' computer, just as if they were in a *native*
guest environment.  That way all of the cross-compilation issues are
avoided.

PRoot can also *mix* the execution of host programs and the execution
of guest programs emulated by QEMU user-mode.  This is useful to use
host equivalents of programs that are missing from the guest rootfs
and to speed up build-time by using cross-compilation tools or
CPU-independent programs, like interpreters.

It is worth noting that the guest kernel is never involved, regardless
of whether QEMU user-mode is used or not.  Technically, when guest
programs perform access to system resources, PRoot translates their
requests before sending them to the host kernel.  This means that
guest programs can use host resources (devices, network, ...) just as
if they were "normal" host programs.


Options
=======

The command-line interface is composed of two parts: first PRoot's
options (optional), then the command to launch (``/bin/sh`` if not
specified).  This section describes the options supported by PRoot,
that is, the first part of its command-line interface.


Regular options
---------------

-r path, --rootfs=path
    Use *path* as the new guest root file-system, default is ``/``.

    The specified *path* typically contains a Linux distribution where
    all new programs will be confined.  The default rootfs is ``/``
    when none is specified, this makes sense when the bind mechanism
    is used to relocate host files and directories, see the ``-b``
    option and the ``Examples`` section for details.

    It is recommended to use the ``-R`` option instead.

-b path, --bind=path, -m path, --mount=path
    Make the content of *path* accessible in the guest rootfs.

    This option makes any file or directory of the host rootfs
    accessible in the confined environment just as if it were part of
    the guest rootfs.  By default the host path is bound to the same
    path in the guest rootfs but users can specify any other location
    with the syntax: ``-b *host_path*:*guest_location*``.  If the
    guest location is a symbolic link, it is dereferenced to ensure
    the new content is accessible through all the symbolic links that
    point to the overlaid content.  In most cases this default
    behavior shouldn't be a problem, although it is possible to
    explicitly not dereference the guest location by appending it the
    ``!`` character: ``-b *host_path*:*guest_location!*``.

-q command, --qemu=command
    Execute guest programs through QEMU as specified by *command*.

    Each time a guest program is going to be executed, PRoot inserts
    the QEMU user-mode *command* in front of the initial request.
    That way, guest programs actually run on a virtual guest CPU
    emulated by QEMU user-mode.  The native execution of host programs
    is still effective and the whole host rootfs is bound to
    ``/host-rootfs`` in the guest environment.

-w path, --pwd=path, --cwd=path
    Set the initial working directory to *path*.

    Some programs expect to be launched from a given directory but do
    not perform any ``chdir`` by themselves.  This option avoids the
    need for running a shell and then entering the directory manually.

-v value, --verbose=value
    Set the level of debug information to *value*.

    The higher the integer *value* is, the more detailled debug
    information is printed to the standard error stream.  A negative
    *value* makes PRoot quiet except on fatal errors.

-V, --version, --about
    Print version, copyright, license and contact, then exit.

-h, --help, --usage
    Print the version and the command-line usage, then exit.


Extension options
-----------------

The following options enable built-in extensions.  Technically
developers can add their own features to PRoot or use it as a Linux
process instrumentation engine thanks to its extension mechanism, see
the sources for further details.

-k string, --kernel-release=string
    Set the kernel release and compatibility level to *string*.

    If a program is run on a kernel older than the one expected by its
    GNU C library, the following error is reported: "FATAL: kernel too
    old".  To be able to run such programs, PRoot can emulate some of
    the syscalls that are available in the kernel release specified by
    *string* but that are missing in the current kernel.  With some
    versions of the GNU C library, the following tweak is required if
    this fatal error still happens when this option is enabled::

      cd path/to/rootfs
      sed --in-place=.bak s/Linux/PRoot/ \
          lib*/ld-linux*.so.2 lib*/*/ld-linux*.so.2

-0, --root-id
    Force some syscalls to behave as if executed by "root".

    Some programs will refuse to work if they are not run with "root"
    privileges, even if there is no technical reason for that.  This
    is typically the case with package managers.  This option allows
    users to bypass this kind of limitation by faking the user/group
    identity, and by faking the success of some operations like
    changing the ownership of files, changing the root directory to
    ``/``, ...  Note that this option is quite limited compared to
    ``fakeroot``.


Alias options
-------------

The following options are aliases for handy sets of options.

-R path
    Alias: ``-r *path*`` + a couple of recommended ``-b``.

    Programs isolated in *path*, a guest rootfs, might still need to
    access information about the host system, as it is illustrated in
    the ``Examples`` section of the manual.  These host information
    are typically: user/group definition, network setup, run-time
    information, users' files, ...  On all Linux distributions, they
    all lie in a couple of host files and directories that are
    automatically bound by this option:

    * /etc/host.conf
    * /etc/hosts
    * /etc/hosts.equiv
    * /etc/mtab
    * /etc/netgroup
    * /etc/networks
    * /etc/passwd
    * /etc/group
    * /etc/nsswitch.conf
    * /etc/resolv.conf
    * /etc/localtime
    * /dev/
    * /sys/
    * /proc/
    * /tmp/
    * $HOME

-B, -M
    obsolete, use ``-R`` instead.

-Q command
    obsolete, use ``-q`` and ``-R`` instead.


Exit Status
===========

If an internal error occurs, ``proot`` returns a non-zero exit status,
otherwise it returns the exit status of the last terminated
program. When an error has occurred, the only way to know if it comes
from the last terminated program or from ``proot`` itself is to have a
look at the error message.


Files
=====

PRoot reads links in ``/proc/<pid>/fd/`` to support `openat(2)`-like
syscalls made by the guest programs.


Examples
========

In the following examples the directories ``/mnt/slackware-8.0`` and
``/mnt/armslack-12.2/`` contain a Linux distribution respectively made
for x86 CPUs and ARM CPUs.


``chroot`` equivalent
---------------------

To execute a command inside a given Linux distribution, just give
``proot`` the path to the guest rootfs followed by the desired
command.  The example below executes the program ``cat`` to print the
content of a file::

    proot -r /mnt/slackware-8.0/ cat /etc/motd
    
    Welcome to Slackware Linux 8.0

The default command is ``/bin/sh`` when none is specified. Thus the
shortest way to confine an interactive shell and all its sub-programs
is::

    proot -r /mnt/slackware-8.0/
    
    $ cat /etc/motd
    Welcome to Slackware Linux 8.0


``mount --bind`` equivalent
---------------------------

The bind mechanism permits to relocate files and directories.  This is
typically useful to cheat programs that perform access to hard-coded
locations, like some installation scripts::

    proot -b /tmp/alternate_opt:/opt
    
    $ cd to/sources
    $ make install
    [...]
    install -m 755 prog "/opt/bin"
    [...] # prog is installed in "/tmp/alternate_opt/bin" actually

As shown in this example, it is possible to bind over files not even
owned by the user.  This can be used to *overlay* system configuration
files, for instance the DNS setting::

    ls -l /etc/hosts
    -rw-r--r-- 1 root root 675 Mar  4  2011 /etc/hosts

::

    proot -b ~/alternate_hosts:/etc/hosts
    
    $ echo '1.2.3.4 google.com' > /etc/hosts
    $ resolveip google.com
    IP address of google.com is 1.2.3.4
    $ echo '5.6.7.8 google.com' > /etc/hosts
    $ resolveip google.com
    IP address of google.com is 5.6.7.8

Another example: on most Linux distributions ``/bin/sh`` is a symbolic
link to ``/bin/bash``, whereas it points to ``/bin/dash`` on Debian
and Ubuntu.  As a consequence a ``#!/bin/sh`` script tested with Bash
might not work with Dash.  In this case, the binding mechanism of
PRoot can be used to set non-disruptively ``/bin/bash`` as the default
``/bin/sh`` on these two Linux distributions::

    proot -b /bin/bash:/bin/sh [...]

Because ``/bin/sh`` is initially a symbolic link to ``/bin/dash``, the
content of ``/bin/bash`` is actually bound over this latter::

    proot -b /bin/bash:/bin/sh
    
    $ md5sum /bin/sh
    089ed56cd74e63f461bef0fdfc2d159a  /bin/sh
    $ md5sum /bin/bash
    089ed56cd74e63f461bef0fdfc2d159a  /bin/bash
    $ md5sum /bin/dash
    089ed56cd74e63f461bef0fdfc2d159a  /bin/dash

In most cases this shouldn't be a problem, but it is still possible to
strictly bind ``/bin/bash`` over ``/bin/sh`` -- without dereferencing
it -- by specifying the ``!`` character at the end::

    proot -b '/bin/bash:/bin/sh!'
    
    $ md5sum /bin/sh
    089ed56cd74e63f461bef0fdfc2d159a  /bin/sh
    $ md5sum /bin/bash
    089ed56cd74e63f461bef0fdfc2d159a  /bin/bash
    $ md5sum /bin/dash
    c229085928dc19e8d9bd29fe88268504  /bin/dash


``chroot`` + ``mount --bind`` equivalent
----------------------------------------

The two features above can be combined to make any file from the host
rootfs accessible in the confined environment just as if it were
initially part of the guest rootfs.  It is sometimes required to run
programs that rely on some specific files::

    proot -r /mnt/slackware-8.0/
    
    $ ps -o tty,command
    Error, do this: mount -t proc none /proc

works better with::

    proot -r /mnt/slackware-8.0/ -b /proc
    
    $ ps -o tty,command
    TT       COMMAND
    ?        -bash
    ?        proot -b /proc /mnt/slackware-8.0/
    ?        /lib/ld-linux.so.2 /bin/sh
    ?        /lib/ld-linux.so.2 /usr/bin/ps -o tty,command

Actually there's a bunch of such specific files, that's why PRoot
provides the option ``-R`` to bind automatically a pre-defined list of
recommended paths::

    proot -R /mnt/slackware-8.0/
    
    $ ps -o tty,command
    TT       COMMAND
    pts/6    -bash
    pts/6    proot -R /mnt/slackware-8.0/
    pts/6    /lib/ld-linux.so.2 /bin/sh
    pts/6    /lib/ld-linux.so.2 /usr/bin/ps -o tty,command


``chroot`` + ``mount --bind`` + ``binfmt_misc`` equivalent
----------------------------------------------------------

PRoot uses QEMU user-mode to execute programs built for a CPU
architecture incompatible with the host one.  From users'
point-of-view, guest programs handled by QEMU user-mode are executed
transparently, that is, just like host programs.  To enable this
feature users just have to specify which instance of QEMU user-mode
they want to use with the option ``-q``::

    proot -R /mnt/armslack-12.2/ -q qemu-arm
    
    $ cat /etc/motd
    Welcome to ARMedSlack Linux 12.2

The parameter of the ``-q`` option is actually a whole QEMU user-mode
command, for instance to enable its GDB server on port 1234::

    proot -R /mnt/armslack-12.2/ -q "qemu-arm -g 1234" emacs

PRoot allows to mix transparently the emulated execution of guest
programs and the native execution of host programs in the same
file-system namespace.  It's typically useful to extend the list of
available programs and to speed up build-time significantly.  This
mixed-execution feature is enabled by default when using QEMU
user-mode, and the content of the host rootfs is made accessible
through ``/host-rootfs``::

    proot -R /mnt/armslack-12.2/ -q qemu-arm
    
    $ file /bin/echo
    [...] ELF 32-bit LSB executable, ARM [...]
    $ /bin/echo 'Hello world!'
    Hello world!

    $ file /host-rootfs/bin/echo
    [...] ELF 64-bit LSB executable, x86-64 [...]
    $ /host-rootfs/bin/echo 'Hello mixed world!'
    Hello mixed world!

Since both host and guest programs use the guest rootfs as ``/``,
users may want to deactivate explicitly cross-filesystem support found
in most GNU cross-compilation tools.  For example with GCC configured
to cross-compile to the ARM target::

    proot -R /mnt/armslack-12.2/ -q qemu-arm
    
    $ export CC=/host-rootfs/opt/cross-tools/arm-linux/bin/gcc
    $ export CFLAGS="--sysroot=/"   # could be optional indeed
    $ ./configure; make

As with regular files, a host instance of a program can be bound over
its guest instance.  Here is an example where the guest binary of
``make`` is overlaid by the host one::

   proot -R /mnt/armslack-12.2/ -q qemu-arm -b /usr/bin/make
   
   $ which make
   /usr/bin/make
   $ make --version # overlaid
   GNU Make 3.82
   Built for x86_64-slackware-linux-gnu

It's worth mentioning that even when mixing the native execution of
host programs and the emulated execution of guest programs, they still
believe they are running in a native guest environment.  As a
demonstration, here is a partial output of a typical ``./configure``
script::

    checking whether the C compiler is a cross-compiler... no


Downloads
=========

PRoot
-----

The latest release of PRoot is packaged on http://packages.proot.me
and sources are hosted on http://github.proot.me.  Also, highly
compatible binaries are available on http://static.proot.me for a
couple of architectures.


Rootfs
------

Here follows a couple of URLs where some rootfs archives can be freely
downloaded.  Note that the errors reported by ``tar`` when extracting
these archives can be safely ignored.  Obviously these files are not
required when PRoot is used as a ``mount --bind`` equivalent only.

* Slackware, Arch, Fedora for ARM:

  * ftp://ftp.armedslack.org/slackwarearm/slackwarearm-devtools/minirootfs/roots/
  * http://archlinuxarm.org/developers/downloads
  * http://ftp.linux.org.uk/pub/linux/arm/fedora/rootfs/

* CentOS, Debian, Fedora, Scientific, Suse, Ubuntu, ALT, Arch, CERN,
  Gentoo, OpenSuse, Openwall, Slackware, SLES, and etc. for x86 and
  x86_64 CPUs:

  * http://download.openvz.org/template/precreated/
  * http://cdimage.ubuntu.com/ubuntu-core/releases/

* Gentoo for a lot of architectures:

  * http://distfiles.gentoo.org/releases/

Technically such rootfs archive can be created by running the
following command on the expected Linux distribution::

    tar --one-file-system --create --gzip --file my_rootfs.tar.gz /


QEMU user-mode
--------------

QEMU user-mode is required only if the guest rootfs was made for a CPU
architecture incompatible with the host one, for instance when using a
ARM rootfs on a x86_64 computer.  This package can be installed either
from http://qemu.proot.me or from the host package manager under the
name of "qemu-user" on most Linux distro.  In case one would like to
build QEMU user-mode from sources, the ``--enable-linux-user`` option
has to be specified to the ``./configure`` script.


See Also
========

chroot(1), mount(8), binfmt_misc, ptrace(2), qemu(1), sb2(1),
bindfs(1), fakeroot(1), fakechroot(1)


Colophon
========

Visit http://proot.me for help, bug reports, suggestions, patchs, ...
Copyright (C) 2013 STMicroelectronics, licensed under GPL v2 or later.

::

     _____ _____              ___
    |  __ \  __ \_____  _____|   |_
    |   __/     /  _  \/  _  \    _|
    |__|  |__|__\_____/\_____/\____|