mount --bind, and
binfmt_misc without privilege/setup
proot [option] ... /path/to/guest/rootfs [program [arg] ...]
PRoot is a user-space implementation of
binfmt_misc. This means that users don't need any privilege
or setup to do things like: using an arbitrary directory as the new
root file-system or making files accessible somewhere else in the
file-system hierarchy or executing programs built for another CPU
architecture transparently through QEMU user-mode. Technically PRoot
ptrace, an unprivileged system-call available in every
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.
The command-line interface is composed of three ordered parts:
PRoot's options (optional), path to the guest rootfs (mandatory), and
the command to launch (
/bin/sh by default).
This section describes the options supported by PRoot, that is, the first part of its command-line interface.
|-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:
|-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
This option is automatically enabled by the
|-w path, --pwd=path, --cwd=path|
Set the initial working directory to path, default is
Some programs expect to be launched from a given directory but do
not perform any
Allow the execution of unknown syscalls.
PRoot has to know the semantics of a syscall to translate its arguments. This is why any syscall that PRoot isn't aware of is blocked. This option disables this default behavior.
|-k string, --kernel-release=string|
Technically the GNU C library relies on syscalls provided by the kernel that's why it performs a sanity check at each program start-up to verify whether the current kernel is known to be compatible. If users are running a GNU C library that expects a kernel more recent than the one used on their computers, they will get the error "FATAL: kernel too old". This option allows users to cheat this sanity check by faking the release number of the current kernel. This option should be used with care since it does not improve the compatibility.
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
|-v, --verbose||Increase the level of debug information.|
|-V, --version, --about|
|Print version, copyright, license and contact, then exit.|
|-h, --help, --usage|
|Print the version and the command-line usage, then exit.|
The following options are aliases for handy sets of options.
There are a couple of bindings that are needed for most guest programs to behave correctly regarding the configuration part of the host computer which is not specific to the host Linux distribution, such as: user/group information, network setup, run-time information, users' files, ... This highly recommended option enables the following bindings:
This option is highly recommended when using QEMU user-mode; it enables all the recommended bindings.
Make the current working directory accessible in the guest rootfs
and then use it as the initial working directory. This option is
typically useful to launch
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.
PRoot reads links in
/proc/<pid>/fd/ to support openat(2)-like
syscalls made by the guest programs.
In the following examples the directories
/mnt/armslack-12.2/ contain a Linux distribution respectively made
for x86 CPUs and ARM CPUs.
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 /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
proot /mnt/slackware-8.0/ $ cat /etc/motd Welcome to Slackware Linux 8.0
mount --bind equivalent
-b, short for
--bind, makes 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 /mnt/slackware-8.0/ $ ps -o tty,command Error, do this: mount -t proc none /proc
works better with:
proot -b /proc /mnt/slackware-8.0/ $ 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
-B to bind automatically a pre-defined list of
proot -B /mnt/slackware-8.0/ $ ps -o tty,command TT COMMAND pts/6 -bash pts/6 proot -B /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
mount --bind equivalent
The bind mechanism can also be used to relocate files and directories
in the host rootfs by using
/ as the path to the guest rootfs and
by specifying an alternate binding location (separated by
is typically useful to cheat programs that perform access to
hard-coded locations, like some installation scripts:
proot -b /tmp/alternate_usr:/usr / $ cd to/sources $ make install [...] install -m 755 prog "/usr/bin" [...] # prog was installed in "/tmp/alternate_usr/bin" actually
It can also be used to substitute system configuration files, for example the DNS setting:
proot -b ./alternate_resolv.conf:/etc/resolv.conf / resolveip google.com
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 (this latter implies
proot -Q qemu-arm /mnt/armslack-12.2/ $ cat /etc/motd Welcome to ARMedSlack Linux 12.2
The parameter of the
-q/-Q option is actually a whole QEMU
user-mode command, for instance to enable its GDB server on port
proot -Q "qemu-arm -g 1234" /mnt/armslack-12.2/ 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
proot -Q qemu-arm /mnt/armslack-12.2/ $ 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 -Q qemu-arm /mnt/armslack-12.2/ $ 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 -Q qemu-arm -b /usr/bin/make /mnt/armslack-12.2/ $ 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
checking whether the C compiler is a cross-compiler... no
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,
that is, when the path to the guest rootfs is
CentOS, Debian, Fedora, Scientific, Suse, Ubuntu for x86 and x86_64 CPUs, from the OpenVZ project:
ALT, Arch, CERN, Gentoo, OpenSuse, Openwall, Slackware, SLES, and etc. for x86 and x86_64 CPUs, from the OpenVZ community:
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 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
has to be specified to the
chroot(1), mount(8), binfmt_misc, ptrace(2), qemu(1), sb2(1), bindfs(1), fakeroot(1), fakechroot(1)
Visit http://proot.me for help, bug reports, suggestions, patchs, ... Copyright (C) 2012 STMicroelectronics, licensed under GPL v2 or later.