Add bwrap as backend for ns

This commit is contained in:
Filippo Squillace 2020-03-14 17:05:40 +01:00
parent 538e87f036
commit 9bfd7e047d
12 changed files with 387 additions and 169 deletions

View file

@ -21,10 +21,12 @@ script:
- bash ./tests/unit-tests/unit-tests.sh
# Multiple tests against different execution modes:
- junest proot --fakeroot -- ${PWD}/lib/checks/check.sh
- junest ns -- ${PWD}/lib/checks/check.sh
- sudo -E ${PWD}/bin/junest groot -- ${PWD}/lib/checks/check.sh --run-root-tests
- junest proot --fakeroot -- ${PWD}/lib/checks/check.sh --skip-aur-tests
- junest proot -- ${PWD}/lib/checks/check.sh --skip-aur-tests --use-sudo
- junest ns --fakeroot -- ${PWD}/lib/checks/check.sh --skip-aur-tests
- junest ns -- ${PWD}/lib/checks/check.sh --use-sudo
- sudo -E ${PWD}/bin/junest groot -- ${PWD}/lib/checks/check.sh --run-root-tests --skip-aur-tests
- yes | junest setup --delete
- JUNEST_HOME=~/.junest-arm junest proot --fakeroot -- ${PWD}/lib/checks/check.sh
- JUNEST_HOME=~/.junest-arm junest proot --fakeroot -- ${PWD}/lib/checks/check.sh --skip-aur-tests
- yes | JUNEST_HOME=~/.junest-arm junest setup --delete

View file

@ -28,8 +28,9 @@ The lightweight Arch Linux based distro that runs upon any Linux distros without
Description
===========
**JuNest** (Jailed User NEST) is a lightweight Arch Linux based distribution that allows to have
an isolated GNU/Linux environment inside any generic host GNU/Linux OS
**JuNest** (Jailed User NEST) is a lightweight Arch Linux based distribution
that allows to have disposable and isolated GNU/Linux environments
within any generic GNU/Linux host OS
and without the need to have root privileges for installing packages.
JuNest contains mainly the package managers (called [pacman](https://wiki.archlinux.org/index.php/Pacman)
@ -86,14 +87,22 @@ By default, JuNest run via the Linux namespaces (aka `ns`) as the backend progra
junest
```
You can use the command `sudo` to acquire fakeroot privileges and
install/remove packages.
Alternatively, you can access root privileges without using `sudo` with the
`-f` option:
```sh
junest -f
```
Another execution mode is via [Proot](https://wiki.archlinux.org/index.php/Proot):
```sh
junest proot [-f]
```
Where `-f` allow fakeroot access to install/remove packages.
There are multiple backend programs, each with its own pros/cons.
To know more about the JuNest execution modes depending on the backend program
used, see the [Usage](#usage) section below.
@ -105,15 +114,20 @@ Have fun!
If you are new on Arch Linux and you are not familiar with `pacman` package manager
visit the [pacman rosetta page](https://wiki.archlinux.org/index.php/Pacman_Rosetta).
JuNest provides a modified version of `makepkg` in `/opt/makepkg/bin` that
allows you to build packages from [AUR](https://aur.archlinux.org/) repository.
Remember that in order to build packages, `base-devel` package group is required
In `ns` mode, you can easily install package from [AUR](https://aur.archlinux.org/) repository
using the already available [`yay`](https://aur.archlinux.org/packages/yay/)
command. In `proot` mode, JuNest does no longer support the building of AUR packages.
**Remember** that in order to build packages from source, `base-devel` package group is required
first:
```sh
pacman -Sy --ignore sudo base-devel
```
JuNest uses a modified version of `sudo`. That's why the original `sudo`
package has to be ignored in the previous command.
Installation
============
@ -125,14 +139,14 @@ Before installing JuNest be sure that all dependencies are properly installed in
- [bash (>=4.0)](https://www.gnu.org/software/bash/)
- [GNU coreutils](https://www.gnu.org/software/coreutils/)
The minimum recommended Linux kernel of the host OS is 2.6.32 on x86 (64 bit)
In `proot` mode, the minimum recommended Linux kernel for the host OS is 2.6.32 on x86 (64 bit)
and ARM architectures. It is still possible to run JuNest on lower
2.6.x host OS kernels but errors may appear, and some applications may
crash. For further information, read the [Troubleshooting](#troubleshooting)
section below.
## Method one (Recommended) ##
## Installation from git repository ##
Just clone the JuNest repo somewhere (for example in ~/.local/share/junest):
git clone git://github.com/fsquillace/junest ~/.local/share/junest
@ -142,14 +156,6 @@ Just clone the JuNest repo somewhere (for example in ~/.local/share/junest):
If you are using an Arch Linux system you can, alternatively, install JuNest from the [AUR repository](https://aur.archlinux.org/packages/junest-git/).
After installing junest will be located in `/opt/junest/`
## Method two ##
Alternatively, another installation method would be to directly download the JuNest image and place it to the default directory `~/.junest`:
ARCH=<one of "x86_64", "arm">
mkdir ~/.junest
curl https://s3-eu-west-1.amazonaws.com/junest-repo/junest/junest-${ARCH}.tar.gz | tar -xz -C ~/.junest
export PATH=~/.junest/opt/junest/bin:$PATH
Usage
=====
There are three different ways you can run JuNest depending on the backend program you decide to use.
@ -173,7 +179,12 @@ provides the state of the user namespace on several GNU/Linux distros.
In order to run JuNest via Linux namespaces:
- As fakeroot - Allow to install/remove packages: `junest ns` or `junest`
- As normal user - Allow to make basic operations or install/remove packages
with `sudo` command: `junest ns` or `junest`
- As fakeroot - Allow to install/remove packages: `junest ns -f` or `junest -f`
This mode is based on the fantastic
[`bubblewrap`](https://github.com/containers/bubblewrap) command.
PRoot based
-----------
@ -211,8 +222,8 @@ The following table shows the capabilities that each backend program is able to
| | QEMU | Root privileges required | Manage Official Packages | Manage AUR Packages | Portability | Support | User modes |
| --- | ---- | ------------------------ | ------------------------ | ------------------- | ----------- | ------- | ---------- |
| **Linux Namespaces** | NO | NO | YES | YES | Poor | YES | `fakeroot` only |
| **Proot** | YES | NO | YES | YES | YES | Poor | Normal user and `fakeroot` |
| **Linux Namespaces** | NO | NO | YES | YES | Poor | YES | Normal user and `fakeroot` |
| **Proot** | YES | NO | YES | NO | YES | Poor | Normal user and `fakeroot` |
| **Chroot** | NO | YES | YES | YES | YES | YES | `root` only |
Advanced usage
@ -343,6 +354,17 @@ For Arch Linux related FAQs take a look at the [General troubleshooting page](ht
> Remember to ignore `sudo` as it conflicts with `sudo-fake` package.
## Can't set user and group as root
> **Q**: In ns mode when installing package I get the following error:
warning: warning given when extracting /usr/file... (Can't set user=0/group=0 for
/usr/file...)
> **A**: This is because as fakeroot is not possible to set the owner/group of
> files as root. The package will still be installed correctly even though this
> message is showed.
## No servers configured for repository ##
> **Q**: Why I cannot install packages?

View file

@ -38,9 +38,9 @@ usage() {
echo -e " Defaults to the host architecture ($ARCH)"
echo -e " -d, --delete Delete $NAME from ${JUNEST_HOME}"
echo
echo -e " n[s] Access via Linux Namespaces using GRoot (Default action)"
echo -e " n[s] Access via Linux Namespaces using BubbleWrap (Default action)"
echo -e " -b, --backend-args <args> Arguments for GRoot backend program"
echo -e " ($CMD groot -b \"--help\" to check out the GRoot options)"
echo -e " ($CMD groot -b \"--help\" to check out the bwrap options)"
echo -e " -n, --no-copy-files Do not copy common etc files into $NAME environment"
echo
echo -e " p[root] Access via PRoot"
@ -138,6 +138,7 @@ function _parse_root_opts() {
function _parse_ns_opts() {
# Options:
OPT_FAKEROOT=false
OPT_BACKEND_ARGS=false
BACKEND_ARGS=""
OPT_NO_COPY_FILES=false
@ -145,6 +146,7 @@ function _parse_ns_opts() {
while [[ -n "$1" ]]
do
case "$1" in
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
-b|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;;
-n|--no-copy-files) OPT_NO_COPY_FILES=true ; shift ;;
--) shift ; break ;;
@ -250,12 +252,16 @@ function execute_operation() {
local run_env
if $ACT_NAMESPACE; then
run_env=run_env_with_namespace
if $OPT_FAKEROOT; then
run_env=run_env_as_bwrap_fakeroot
else
run_env=run_env_as_bwrap_user
fi
elif $ACT_PROOT; then
if $OPT_FAKEROOT; then
run_env=run_env_as_fakeroot
run_env=run_env_as_proot_fakeroot
else
run_env=run_env_as_user
run_env=run_env_as_proot_user
fi
elif $ACT_GROOT; then
run_env=run_env_as_groot

View file

@ -9,15 +9,26 @@
#
# vim: ft=sh
set -eu
set -e
OPT_RUN_ROOT_TESTS=${1:-false}
RUN_ROOT_TESTS=false
[[ ${OPT_RUN_ROOT_TESTS} == "--run-root-tests" ]] && RUN_ROOT_TESTS=true
OPT_SKIP_AUR_TESTS=${1:-false}
SKIP_AUR_TESTS=false
[[ ${OPT_SKIP_AUR_TESTS} == "--skip-aur-tests" ]] && SKIP_AUR_TESTS=true
USE_SUDO=false
while [[ -n "$1" ]]
do
case "$1" in
--run-root-tests) RUN_ROOT_TESTS=true ; shift ;;
--skip-aur-tests) SKIP_AUR_TESTS=true ; shift ;;
--use-sudo) USE_SUDO=true ; shift ;;
*) die "Invalid option $1" ;;
esac
done
set -u
SUDO=""
[[ -n $USE_SUDO ]] && SUDO="sudo"
JUNEST_HOME=${JUNEST_HOME:-$HOME/.junest}
@ -36,49 +47,42 @@ info "Initial JuNest setup..."
trap "[[ -e /etc/pacman.d/gnupg/S.gpg-agent ]] && gpg-connect-agent -S /etc/pacman.d/gnupg/S.gpg-agent killagent /bye" QUIT EXIT ABRT KILL TERM INT
echo "Server = ${DEFAULT_MIRROR}" >> /etc/pacman.d/mirrorlist
pacman --noconfirm -Syy
$SUDO pacman --noconfirm -Syy
pacman-key --init
$SUDO pacman-key --init
pacman --noconfirm -S archlinux-keyring
pacman-key --populate archlinux
$SUDO pacman --noconfirm -S archlinux-keyring
$SUDO pacman-key --populate archlinux
pacman --noconfirm -S archlinuxarm-keyring || echo "No ARM keyring detected"
pacman-key --populate archlinuxarm || echo "No ARM keyring detected"
$SUDO pacman --noconfirm -S archlinuxarm-keyring || echo "No ARM keyring detected"
$SUDO pacman-key --populate archlinuxarm || echo "No ARM keyring detected"
pacman --noconfirm -Su
pacman --noconfirm -S grep coreutils
pacman --noconfirm -S $(pacman -Sg base-devel | cut -d ' ' -f 2 | grep -v sudo)
$SUDO pacman --noconfirm -Su
$SUDO pacman --noconfirm -S grep coreutils
$SUDO pacman --noconfirm -S $(pacman -Sg base-devel | cut -d ' ' -f 2 | grep -v sudo)
info "Checking basic executables work..."
pacman -Qi pacman 1> /dev/null
/opt/makepkg/bin/makepkg --help 1> /dev/null
$SUDO pacman -Qi pacman 1> /dev/null
/opt/proot/proot-$ARCH --help 1> /dev/null
repo_package1=tree
echo "Checking ${repo_package1} package from official repo..."
pacman --noconfirm -S ${repo_package1}
$SUDO pacman --noconfirm -S ${repo_package1}
tree -L 1
pacman --noconfirm -Rsn ${repo_package1}
$SUDO pacman --noconfirm -Rsn ${repo_package1}
repo_package2=iftop
info "Checking ${repo_package2} package from official repo..."
pacman --noconfirm -S ${repo_package2}
$RUN_ROOT_TESTS && iftop -t -s 5
pacman --noconfirm -Rsn ${repo_package2}
$SUDO pacman --noconfirm -S ${repo_package2}
$RUN_ROOT_TESTS && $SUDO iftop -t -s 5
$SUDO pacman --noconfirm -Rsn ${repo_package2}
if ! $SKIP_AUR_TESTS
then
aur_package=tcptraceroute
info "Checking ${aur_package} package from AUR repo..."
maindir=$(mktemp -d -t ${CMD}.XXXXXXXXXX)
builtin cd ${maindir}
curl -L -J -O -k "https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=${aur_package}"
# -A allows to ignore arch for ARM
/opt/makepkg/bin/makepkg -Asfc --noconfirm
pacman --noconfirm -U ${aur_package}*.pkg.tar.xz
pacman --noconfirm -Rsn ${aur_package}
yay --noconfirm -S ${aur_package}
$SUDO pacman --noconfirm -Rsn ${aur_package}
fi
# The following ensures that the gpg agent gets killed (if exists)

View file

@ -8,13 +8,6 @@
#
# vim: ft=sh
function _check_package(){
if ! pacman -Qq $1 > /dev/null
then
die "Package $1 must be installed"
fi
}
function _install_pkg_from_aur(){
local maindir=$1
local pkgname=$2
@ -35,15 +28,50 @@ function _install_pkg(){
sudo pacman --noconfirm --root ${maindir}/root -U *.pkg.tar.xz
}
function _prepare() {
# ArchLinux System initialization
sudo pacman --noconfirm -Syu
sudo pacman -S --noconfirm base-devel
sudo pacman -S --noconfirm git arch-install-scripts
}
function _install_proot_and_qemu(){
local maindir="$1"
local main_repo=https://s3-eu-west-1.amazonaws.com/${CMD}-repo
proot_link=${main_repo}/proot
qemu_link=${main_repo}/qemu
info "Installing proot static binaries"
sudo bash -c "
mkdir -p '${maindir}/root/opt/proot/'
curl '$proot_link/proot-x86_64' > '${maindir}/root/opt/proot/proot-x86_64'
curl '$proot_link/proot-arm' > '${maindir}/root/opt/proot/proot-arm'
chmod -R 755 '${maindir}/root/opt/proot/'
"
info "Installing qemu static binaries"
sudo bash -c "
mkdir -p '${maindir}/root/opt/qemu/'
if [[ $ARCH == 'arm' ]]
then
curl '${qemu_link}/arm/qemu-arm-static-x86_64' > '${maindir}/root/opt/qemu/qemu-arm-static-x86_64'
elif [[ $ARCH == 'x86_64' ]]
then
curl '${qemu_link}/x86_64/qemu-x86_64-static-arm' > '${maindir}/root/opt/qemu/qemu-x86_64-static-arm'
fi
chmod -R 755 '${maindir}/root/opt/qemu/'
"
}
function build_image_env(){
umask 022
# The function must runs on ArchLinux with non-root privileges.
# This is because installing AUR packages can be done by normal users only.
(( EUID == 0 )) && \
die "You cannot build with root privileges."
_check_package arch-install-scripts
_check_package gcc
_prepare
local disable_validation=$1
@ -54,33 +82,41 @@ function build_image_env(){
info "Installing pacman and its dependencies..."
# The archlinux-keyring and libunistring are due to missing dependencies declaration in ARM archlinux
# All the essential executables (ln, mkdir, chown, etc) are in coreutils
# unshare command belongs to util-linux
# bwrap command belongs to bubblewrap
local arm_keyring=""
[[ $(uname -m) == *"arm"* ]] && arm_keyring="archlinuxarm-keyring"
sudo pacstrap -G -M -d ${maindir}/root pacman coreutils libunistring archlinux-keyring $arm_keyring util-linux
sudo pacstrap -G -M -d ${maindir}/root pacman coreutils libunistring archlinux-keyring $arm_keyring bubblewrap
sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist"
sudo mkdir -p ${maindir}/root/run/lock
# AUR packages requires non-root user to be compiled. proot fakes the user to 10
_install_pkg ${maindir} "$JUNEST_BASE/pkgs/sudo-fake"
info "Install ${NAME} script..."
_install_pkg_from_aur ${maindir} "${CMD}-git" "${CMD}.install"
info "Install yay..."
sudo pacman --noconfirm -S go
_install_pkg_from_aur ${maindir} "yay"
_install_proot_and_qemu "${maindir}"
echo "Generating the metadata info"
sudo install -d -m 755 "${maindir}/root/etc/${CMD}"
sudo bash -c "echo 'JUNEST_ARCH=$ARCH' > ${maindir}/root/etc/${CMD}/info"
info "Generating the locales..."
# sed command is required for locale-gen
# sed command is required for locale-gen but it is required by fakeroot
# and cannot be removed
# localedef (called by locale-gen) requires gzip
sudo pacman --noconfirm --root ${maindir}/root -S sed gzip
sudo ln -sf /usr/share/zoneinfo/posix/UTC ${maindir}/root/etc/localtime
sudo bash -c "echo 'en_US.UTF-8 UTF-8' >> ${maindir}/root/etc/locale.gen"
sudo ${maindir}/root/opt/junest/bin/groot ${maindir}/root locale-gen
sudo ${JUNEST_BASE}/bin/groot ${maindir}/root locale-gen
sudo bash -c "echo LANG=\"en_US.UTF-8\" >> ${maindir}/root/etc/locale.conf"
sudo pacman --noconfirm --root ${maindir}/root -Rsn sed gzip
sudo pacman --noconfirm --root ${maindir}/root -Rsn gzip
info "Setting up the pacman keyring (this might take a while!)..."
# gawk command is required for pacman-key
sudo pacman --noconfirm --root ${maindir}/root -S gawk
sudo ${maindir}/root/opt/junest/bin/groot -b /dev ${maindir}/root bash -c '
sudo ${JUNEST_BASE}/bin/groot -b /dev ${maindir}/root bash -c '
pacman-key --init;
for keyring_file in /usr/share/pacman/keyrings/*.gpg;
do
@ -105,9 +141,11 @@ function build_image_env(){
then
mkdir -p ${maindir}/root_test
$TAR -zxpf ${imagefile} -C "${maindir}/root_test"
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} proot -f ${JUNEST_BASE}/lib/checks/check.sh
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} ns ${JUNEST_BASE}/lib/checks/check.sh
JUNEST_HOME="${maindir}/root_test" sudo -E ${JUNEST_BASE}/bin/${CMD} groot ${JUNEST_BASE}/lib/checks/check.sh --run-root-tests
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} proot --fakeroot ${JUNEST_BASE}/lib/checks/check.sh --skip-aur-tests
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} proot ${JUNEST_BASE}/lib/checks/check.sh --skip-aur-tests --use-sudo
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} ns --fakeroot ${JUNEST_BASE}/lib/checks/check.sh --skip-aur-tests
JUNEST_HOME="${maindir}/root_test" ${JUNEST_BASE}/bin/${CMD} ns ${JUNEST_BASE}/lib/checks/check.sh --use-sudo
JUNEST_HOME="${maindir}/root_test" sudo -E ${JUNEST_BASE}/bin/${CMD} groot ${JUNEST_BASE}/lib/checks/check.sh --run-root-tests --skip-aur-tests
fi
sudo cp ${maindir}/output/${imagefile} ${ORIGIN_WD}

View file

@ -81,6 +81,7 @@ CP=cp
# Used for checking user namespace in config.gz file
ZGREP=zgrep
UNSHARE=unshare
BWRAP=bwrap
LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
@ -139,7 +140,17 @@ function unshare_cmd(){
then
$UNSHARE "$@"
else
die "Error: Something went wrong with unshare command. Exiting"
die "Error: Something went wrong while executing unshare command. Exiting"
fi
}
function bwrap_cmd(){
# TODO re-evaluate this strategy:
if $LD_EXEC ${JUNEST_HOME}/usr/bin/$BWRAP --dev-bind / / "${SH[0]}" "-c" ":"
then
$LD_EXEC ${JUNEST_HOME}/usr/bin/$BWRAP "${@}"
else
die "Error: Something went wrong while executing bwrap command. Exiting"
fi
}

View file

@ -1,9 +1,8 @@
#!/usr/bin/env bash
#
# This module contains all namespace functionalities for JuNest.
# This module contains functionalities for accessing to JuNest via bubblewrap.
#
# http://man7.org/linux/man-pages/man7/namespaces.7.html
# http://man7.org/linux/man-pages/man2/unshare.2.html
# https://github.com/containers/bubblewrap
#
# Dependencies:
# - lib/utils/utils.sh
@ -56,46 +55,75 @@ function _check_user_namespace() {
set -e
}
function _run_env_with_namespace(){
function _run_env_with_bwrap(){
local backend_args="$1"
shift
provide_common_bindings
local bindings=${RESULT}
unset RESULT
# Use option -n in groot because umount do not work sometimes.
# As soon as the process terminates, the namespace
# will terminate too with its own mounted directories.
if [[ "$1" != "" ]]
then
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT --no-umount --recursive $bindings $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
JUNEST_ENV=1 bwrap_cmd --bind "$JUNEST_HOME" / --bind "$HOME" "$HOME" --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try ${backend_args} "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
else
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT --no-umount --recursive $bindings $backend_args "$JUNEST_HOME" "${SH[@]}"
JUNEST_ENV=1 bwrap_cmd --bind "$JUNEST_HOME" / --bind "$HOME" "$HOME" --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try ${backend_args} "${SH[@]}"
fi
}
#######################################
# Run JuNest as fakeroot via bwrap
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to bwrap
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# $ROOT_ACCESS_ERROR : If the user is the real root.
# Output:
# - : The command output.
#######################################
function run_env_as_bwrap_fakeroot(){
check_nested_env
local backend_args="$1"
local no_copy_files="$2"
shift 2
_check_user_namespace
check_same_arch
if ! $no_copy_files
then
copy_common_files
fi
_run_env_with_bwrap "--uid 0 $backend_args" "$@"
}
#######################################
# Run JuNest as fakeroot user via user namespace.
# Run JuNest as normal user via bwrap.
#
# Globals:
# JUNEST_HOME (RO) : The JuNest home directory.
# GROOT (RO) : The groot program.
# SH (RO) : Contains the default command to run in JuNest.
# Arguments:
# backend_args ($1) : The arguments to pass to groot
# backend_args ($1) : The arguments to pass to bwrap
# no_copy_files ($2?) : If false it will copy some files in /etc
# from host to JuNest environment.
# cmd ($3-?) : The command to run inside JuNest environment.
# Default command is defined by SH variable.
# Returns:
# $ARCHITECTURE_MISMATCH : If host and JuNest architecture are different.
# Depends on the unshare command outcome.
# Output:
# - : The command output.
#######################################
function run_env_with_namespace() {
function run_env_as_bwrap_user() {
check_nested_env
local backend_args="$1"
@ -117,5 +145,9 @@ function run_env_with_namespace() {
copy_passwd_and_group
fi
_run_env_with_namespace "$backend_args" "$@"
_run_env_with_bwrap "$backend_args" "$@"
}

View file

@ -58,7 +58,7 @@ function _run_env_with_qemu(){
# Output:
# - : The command output.
#######################################
function run_env_as_fakeroot(){
function run_env_as_proot_fakeroot(){
(( EUID == 0 )) && \
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead."
check_nested_env
@ -99,7 +99,7 @@ function run_env_as_fakeroot(){
# Output:
# - : The command output.
#######################################
function run_env_as_user(){
function run_env_as_proot_user(){
(( EUID == 0 )) && \
die_on_status $ROOT_ACCESS_ERROR "You cannot access with root privileges. Use --groot option instead."
check_nested_env

View file

@ -12,7 +12,7 @@ arch=('any')
url=""
license=('GPL')
groups=()
depends=()
depends=('fakeroot' 'fakechroot')
makedepends=()
provides=('sudo')
conflicts=('sudo')
@ -36,7 +36,7 @@ do
esac
done
[[ -z "\${@}" ]] || "\${@}"
[[ -z "\${@}" ]] || fakechroot fakeroot "\${@}"
EOF
chmod 755 "${pkgdir}/usr/bin/sudo"

View file

@ -37,11 +37,11 @@ function setup_env_from_file(){
function setup_env(){
echo "setup_env($1)"
}
function run_env_as_fakeroot(){
function run_env_as_proot_fakeroot(){
local backend_args="$1"
local no_copy_files="$2"
shift 2
echo "run_env_as_fakeroot($backend_args,$no_copy_files,$@)"
echo "run_env_as_proot_fakeroot($backend_args,$no_copy_files,$@)"
}
function run_env_as_groot(){
local backend_args="$1"
@ -55,17 +55,23 @@ function run_env_as_chroot(){
shift 2
echo "run_env_as_chroot($backend_args,$no_copy_files,$@)"
}
function run_env_as_user(){
function run_env_as_proot_user(){
local backend_args="$1"
local no_copy_files="$2"
shift 2
echo "run_env_as_user($backend_args,$no_copy_files,$@)"
echo "run_env_as_proot_user($backend_args,$no_copy_files,$@)"
}
function run_env_with_namespace(){
function run_env_as_bwrap_fakeroot(){
local backend_args="$1"
local no_copy_files="$2"
shift 2
echo "run_env_with_namespace($backend_args,$no_copy_files,$@)"
echo "run_env_as_bwrap_fakeroot($backend_args,$no_copy_files,$@)"
}
function run_env_as_bwrap_user(){
local backend_args="$1"
local no_copy_files="$2"
shift 2
echo "run_env_as_bwrap_user($backend_args,$no_copy_files,$@)"
}
function test_help(){
@ -131,22 +137,22 @@ function test_setup_env(){
assertCommandFail main setup -a arm
}
function test_run_env_as_fakeroot(){
function test_run_env_as_proot_fakeroot(){
assertCommandSuccess main p -f
assertEquals "run_env_as_fakeroot(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot --fakeroot
assertEquals "run_env_as_fakeroot(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main p -f -n
assertEquals "run_env_as_fakeroot(,true,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f -b "-b arg"
assertEquals "run_env_as_fakeroot(-b arg,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f -b "-b arg" -- command -kv
assertEquals "run_env_as_fakeroot(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f command --as
assertEquals "run_env_as_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -f -- command --as
assertEquals "run_env_as_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
is_env_installed(){
return 1
@ -156,18 +162,18 @@ function test_run_env_as_fakeroot(){
function test_run_env_as_user(){
assertCommandSuccess main proot
assertEquals "run_env_as_user(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_user(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main p -n
assertEquals "run_env_as_user(,true,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_user(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -b "-b arg"
assertEquals "run_env_as_user(-b arg,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_user(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -b "-b arg" -- command -ll
assertEquals "run_env_as_user(-b arg,false,command -ll)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_user(-b arg,false,command -ll)" "$(cat $STDOUTF)"
assertCommandSuccess main proot command -ls
assertEquals "run_env_as_user(,false,command -ls)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_user(,false,command -ls)" "$(cat $STDOUTF)"
assertCommandSuccess main proot -- command -ls
assertEquals "run_env_as_user(,false,command -ls)" "$(cat $STDOUTF)"
assertEquals "run_env_as_proot_user(,false,command -ls)" "$(cat $STDOUTF)"
is_env_installed(){
return 1
@ -209,36 +215,73 @@ function test_run_env_as_chroot(){
assertCommandFail main root -f
}
function test_run_env_with_namespace(){
function test_run_env_as_bwrap_fakeroot(){
assertCommandSuccess main n -f
assertEquals "run_env_as_bwrap_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -f
assertEquals "run_env_as_bwrap_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -n -f
assertEquals "run_env_as_bwrap_fakeroot(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -f -b "-b arg"
assertEquals "run_env_as_bwrap_fakeroot(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -f -b "-b arg" -- command -kv
assertEquals "run_env_as_bwrap_fakeroot(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -f command --as
assertEquals "run_env_as_bwrap_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -f -- command --as
assertEquals "run_env_as_bwrap_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main -f
assertEquals "run_env_as_bwrap_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -f
assertEquals "run_env_as_bwrap_fakeroot(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -f -b "-b arg"
assertEquals "run_env_as_bwrap_fakeroot(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -f -b "-b arg" -- command -kv
assertEquals "run_env_as_bwrap_fakeroot(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main -f command --as
assertEquals "run_env_as_bwrap_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main -f -- command --as
assertEquals "run_env_as_bwrap_fakeroot(,false,command --as)" "$(cat $STDOUTF)"
is_env_installed(){
return 1
}
assertCommandFail main ns -f
}
function test_run_env_as_bwrap_user(){
assertCommandSuccess main n
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -n
assertEquals "run_env_with_namespace(,true,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,true,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -b "-b arg"
assertEquals "run_env_with_namespace(-b arg,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -b "-b arg" -- command -kv
assertEquals "run_env_with_namespace(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main ns command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main ns -- command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main
assertEquals "run_env_with_namespace(,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -b "-b arg"
assertEquals "run_env_with_namespace(-b arg,false,)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(-b arg,false,)" "$(cat $STDOUTF)"
assertCommandSuccess main -b "-b arg" -- command -kv
assertEquals "run_env_with_namespace(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(-b arg,false,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess main command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,command --as)" "$(cat $STDOUTF)"
assertCommandSuccess main -- command --as
assertEquals "run_env_with_namespace(,false,command --as)" "$(cat $STDOUTF)"
assertEquals "run_env_as_bwrap_user(,false,command --as)" "$(cat $STDOUTF)"
is_env_installed(){
return 1

View file

@ -15,8 +15,8 @@ function oneTimeSetUp(){
## Mock functions ##
function init_mocks() {
function unshare_cmd(){
echo "unshare $@"
function bwrap_cmd(){
echo "bwrap $@"
}
}
@ -99,17 +99,24 @@ function test_is_user_namespace_enabled_with_userns_clone_file_enabled(){
assertCommandSuccess _is_user_namespace_enabled
}
function test_run_env_with_namespace() {
assertCommandSuccess run_env_with_namespace "" "false" ""
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
function test_run_env_as_bwrap_fakeroot() {
assertCommandSuccess run_env_as_bwrap_fakeroot "" "false"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --uid 0 /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_bwrap_user() {
assertCommandSuccess run_env_as_bwrap_user "" "false"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_with_namespace_no_copy() {
assertCommandSuccess run_env_with_namespace "" "true" ""
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
function test_run_env_as_bwrap_fakeroot_no_copy() {
assertCommandSuccess run_env_as_bwrap_fakeroot "" "true" ""
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --uid 0 /bin/sh --login" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
assertEquals 0 $?
@ -133,33 +140,86 @@ function test_run_env_with_namespace_no_copy() {
assertEquals 0 $?
}
function test_run_env_with_namespace_with_bindings() {
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "false" ""
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
function test_run_env_as_bwrap_user_no_copy() {
assertCommandSuccess run_env_as_bwrap_user "" "true" ""
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try /bin/sh --login" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/host.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/nsswitch.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/resolv.conf ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/hosts.equiv ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/netgroup ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/networks ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/passwd ]]
assertEquals 0 $?
[[ ! -e ${JUNEST_HOME}/etc/group ]]
assertEquals 0 $?
}
function test_run_env_as_bwrap_fakeroot_with_backend_args() {
assertCommandSuccess run_env_as_bwrap_fakeroot "--bind /usr /usr" "false"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --uid 0 --bind /usr /usr /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_bwrap_user_with_backend_args() {
assertCommandSuccess run_env_as_bwrap_user "--bind /usr /usr" "false"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --bind /usr /usr /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_with_namespace_with_command() {
assertCommandSuccess run_env_with_namespace "" "false" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
function test_run_env_as_bwrap_fakeroot_with_command() {
assertCommandSuccess run_env_as_bwrap_fakeroot "" "false" "ls -la"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --uid 0 /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_bwrap_user_with_command() {
assertCommandSuccess run_env_as_bwrap_user "" "false" "ls -la"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_with_namespace "-b /usr -b /lib:/tmp/lib" "false" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT --no-umount --recursive -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
function test_run_env_as_bwrap_fakeroot_with_backend_args_and_command() {
assertCommandSuccess run_env_as_bwrap_fakeroot "--bind /usr /usr" "false" "ls -la"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --uid 0 --bind /usr /usr /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_bwrap_user_with_backend_args_and_command() {
assertCommandSuccess run_env_as_bwrap_user "--bind /usr /usr" "false" "ls -la"
assertEquals "bwrap --bind $JUNEST_HOME / --bind $HOME $HOME --bind /tmp /tmp --proc /proc --dev /dev --unshare-user-try --bind /usr /usr /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_with_namespace_nested_env(){
function test_run_env_as_bwrap_fakeroot_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_with_namespace "" "false" ""
assertCommandFailOnStatus 106 run_env_as_bwrap_fakeroot "" "false" ""
unset JUNEST_ENV
}
function test_run_env_as_bwrap_user_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_bwrap_user "" "false" ""
unset JUNEST_ENV
}

View file

@ -47,26 +47,26 @@ function _test_copy_remaining_files() {
assertEquals 0 $?
}
function test_run_env_as_user(){
function test_run_env_as_proot_user(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_user "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
assertCommandSuccess run_env_as_proot_user "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
SH=("/usr/bin/echo")
assertCommandSuccess run_env_as_user "-k 3.10" "false"
assertCommandSuccess run_env_as_proot_user "-k 3.10" "false"
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
}
function test_run_env_as_user_no_copy(){
function test_run_env_as_proot_user_no_copy(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_user "-k 3.10" "true" "/usr/bin/mkdir" "-v" "/newdir2"
assertCommandSuccess run_env_as_proot_user "-k 3.10" "true" "/usr/bin/mkdir" "-v" "/newdir2"
assertEquals "-b $HOME -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
[[ ! -e ${JUNEST_HOME}/etc/hosts ]]
@ -91,29 +91,29 @@ function test_run_env_as_user_no_copy(){
assertEquals 0 $?
}
function test_run_env_as_user_nested_env(){
function test_run_env_as_proot_user_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_user "" "false"
assertCommandFailOnStatus 106 run_env_as_proot_user "" "false"
unset JUNEST_ENV
}
function test_run_env_as_fakeroot(){
function test_run_env_as_proot_fakeroot(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_fakeroot "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
assertCommandSuccess run_env_as_proot_fakeroot "-k 3.10" "false" "/usr/bin/mkdir" "-v" "/newdir2"
assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
SH=("/usr/bin/echo")
assertCommandSuccess run_env_as_fakeroot "-k 3.10" "false"
assertCommandSuccess run_env_as_proot_fakeroot "-k 3.10" "false"
assertEquals "-0 -b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_nested_env(){
function test_run_env_as_proot_fakeroot_nested_env(){
JUNEST_ENV=1
assertCommandFailOnStatus 106 run_env_as_fakeroot "" "false" ""
assertCommandFailOnStatus 106 run_env_as_proot_fakeroot "" "false" ""
unset JUNEST_ENV
}
@ -121,7 +121,7 @@ function test_run_env_with_quotes(){
_run_env_with_qemu() {
echo $@
}
assertCommandSuccess run_env_as_user "-k 3.10" "false" "bash" "-c" "/usr/bin/mkdir -v /newdir2"
assertCommandSuccess run_env_as_proot_user "-k 3.10" "false" "bash" "-c" "/usr/bin/mkdir -v /newdir2"
assertEquals "-b ${HOME} -b /tmp -b /proc -b /sys -b /dev -r ${JUNEST_HOME} -k 3.10 bash -c /usr/bin/mkdir -v /newdir2" "$(cat $STDOUTF)"
}