Issue #174: Add namespace module and check for user namespace

This commit is contained in:
Filippo Squillace 2017-03-14 23:43:52 +00:00
parent f85c62274f
commit 0ec35a4088
6 changed files with 181 additions and 17 deletions

View file

@ -7,10 +7,13 @@ JUNEST_BASE="$(readlink -f $(dirname $(readlink -f "$0"))/..)"
source "${JUNEST_BASE}/lib/utils/utils.sh"
source "${JUNEST_BASE}/lib/core/common.sh"
source "${JUNEST_BASE}/lib/core/build.sh"
source "${JUNEST_BASE}/lib/core/setup.sh"
source "${JUNEST_BASE}/lib/core/proot.sh"
source "${JUNEST_BASE}/lib/core/chroot.sh"
source "${JUNEST_BASE}/lib/core/namespace.sh"
source "${JUNEST_BASE}/lib/core/proot.sh"
source "${JUNEST_BASE}/lib/core/setup.sh"
###################################
### General functions ###
@ -29,8 +32,11 @@ usage() {
echo
echo -e "Access options:"
echo -e "-f, --fakeroot Run $NAME with fakeroot privileges"
echo -e "-r, --root Run $NAME with root privileges"
echo -e "-p, --proot-args <args> Proot arguments (use $CMD -p \"--help\" to check out the proot options)"
echo -e "-r, --root Run $NAME with root privileges via jchroot"
echo -e "-p, --backend-args <args> Arguments for backend program (PRoot or jchroot)"
echo -e " ($CMD -p \"--help\" to check out the PRoot options"
echo -e " $CMD -u -p \"--help\" to check out the jchroot options)"
echo -e "-u, --user-namespace Use Linux User Namespace instead of PRoot"
echo
echo -e "Building options:"
echo -e "-b, --build-image Build a $NAME image (must run in ArchLinux)"
@ -109,7 +115,7 @@ check_cli(){
then
die "You must access to $NAME with either fakeroot or root permissions"
fi
if $OPT_PROOT_ARGS || $OPT_ARCH
if $OPT_BACKEND_ARGS || $OPT_ARCH
then
if $OPT_BUILD_IMAGE || $OPT_DELETE || $OPT_HELP || \
$OPT_ROOT || $OPT_VERSION || $OPT_DISABLE_VALIDATION || $OPT_CHECK
@ -135,8 +141,9 @@ function parse_arguments(){
IMAGE_FILE=""
OPT_FAKEROOT=false
OPT_ROOT=false
OPT_PROOT_ARGS=false
PROOT_ARGS=""
OPT_USER_NAMESPACE=false
OPT_BACKEND_ARGS=false
BACKEND_ARGS=""
OPT_ARCH=false
ARCH_ARG=""
OPT_BUILD_IMAGE=false
@ -153,7 +160,8 @@ function parse_arguments(){
-i|--setup-from-file) OPT_SETUP_FROM_FILE=true ; shift ; IMAGE_FILE=$1 ; shift ;;
-f|--fakeroot) OPT_FAKEROOT=true ; shift ;;
-r|--root) OPT_ROOT=true ; shift ;;
-p|--proot-args) OPT_PROOT_ARGS=true ; shift ; PROOT_ARGS=$1; shift ;;
-u|--user-namespace) OPT_USER_NAMESPACE=true ; shift ;;
-p|--backend-args) OPT_BACKEND_ARGS=true ; shift ; BACKEND_ARGS=$1; shift ;;
-a|--arch) OPT_ARCH=true ; shift ; ARCH_ARG=$1; shift ;;
-b|--build-image) OPT_BUILD_IMAGE=true ; shift ;;
-n|--disable-validation) OPT_DISABLE_VALIDATION=true ; shift ;;
@ -205,13 +213,22 @@ function execute_operation(){
[ -z "${ARCH_ARG}" ] || \
die "The option --arch cannot be specified since JuNest has already been downloaded in $JUNEST_HOME"
if $OPT_FAKEROOT; then
run_env_as_fakeroot "${PROOT_ARGS}" "${ARGS[@]}"
elif $OPT_ROOT; then
run_env_as_root "${ARGS[@]}"
if $OPT_USER_NAMESPACE; then
if $OPT_FAKEROOT; then
run_env_as_fakeroot_with_namespace "${BACKEND_ARGS}" "${ARGS[@]}"
else
run_env_as_user_with_namespace "${BACKEND_ARGS}" "${ARGS[@]}"
fi
else
run_env_as_user "${PROOT_ARGS}" "${ARGS[@]}"
if $OPT_FAKEROOT; then
run_env_as_fakeroot "${BACKEND_ARGS}" "${ARGS[@]}"
elif $OPT_ROOT; then
run_env_as_root "${ARGS[@]}"
else
run_env_as_user "${BACKEND_ARGS}" "${ARGS[@]}"
fi
fi
}
function cli() {

View file

@ -19,6 +19,7 @@ ARCHITECTURE_MISMATCH=104
ROOT_ACCESS_ERROR=105
NESTED_ENVIRONMENT=106
VARIABLE_NOT_SET=107
NO_CONFIG_FOUND=108
if [ "$JUNEST_ENV" == "1" ]
then
@ -89,6 +90,8 @@ RM=rm
MKDIR=mkdir
GETENT=getent
CP=cp
# Used for checking user namespace in config.gz file
ZGREP=zgrep
LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
@ -120,6 +123,10 @@ function mkdir_cmd(){
$MKDIR $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$MKDIR $@
}
function zgrep_cmd(){
$ZGREP $@ || $LD_EXEC ${JUNEST_HOME}/usr/bin/$ZGREP $@
}
function proot_cmd(){
local proot_args="$1"
shift

47
lib/core/namespace.sh Normal file
View file

@ -0,0 +1,47 @@
#!/usr/bin/env bash
#
# This module contains all namespace functionalities for JuNest.
#
# http://man7.org/linux/man-pages/man7/namespaces.7.html
# http://man7.org/linux/man-pages/man2/unshare.2.html
#
# Dependencies:
# - lib/utils/utils.sh
# - lib/core/common.sh
#
# vim: ft=sh
CONFIG_PROC_FILE="/proc/config.gz"
CONFIG_BOOT_FILE="/boot/config-$($UNAME -r)"
function _is_user_namespace_enabled() {
local config_file=""
if [[ -e $CONFIG_PROC_FILE ]]
then
config_file=$CONFIG_PROC_FILE
elif [[ -e $CONFIG_BOOT_FILE ]]
then
config_file=$CONFIG_BOOT_FILE
else
return $NOT_EXISTING_FILE
fi
if ! zgrep_cmd "CONFIG_USER_NS=y" $config_file
then
return $NO_CONFIG_FOUND
fi
}
function run_env_as_user_with_namespace() {
set +e
_is_user_namespace_enabled
case $? in
$NOT_EXISTING_FILE) warn "Could not understand if user namespace is enabled. No config.gz file found. Proceeding anyway..." ;;
$NO_CONFIG_FOUND) warn "User namespace is not enabled or Kernel too old. Proceeding anyway..." ;;
esac
set -e
}
function run_env_as_fakeroot_with_namespace() {
die_on_status 1 "Not implemented yet"
}

View file

@ -44,17 +44,27 @@ function setup_env(){
echo "setup_env($1)"
}
function run_env_as_fakeroot(){
local proot_args="$1"
local backend_args="$1"
shift
echo "run_env_as_fakeroot($proot_args,$@)"
echo "run_env_as_fakeroot($backend_args,$@)"
}
function run_env_as_root(){
echo "run_env_as_root $@"
}
function run_env_as_user(){
local proot_args="$1"
local backend_args="$1"
shift
echo "run_env_as_user($proot_args,$@)"
echo "run_env_as_user($backend_args,$@)"
}
function run_env_as_fakeroot_with_namespace(){
local backend_args="$1"
shift
echo "run_env_as_fakeroot_with_namespace($backend_args,$@)"
}
function run_env_as_user_with_namespace(){
local backend_args="$1"
shift
echo "run_env_as_user_with_namespace($backend_args,$@)"
}
function test_help(){
@ -164,6 +174,31 @@ function test_run_env_as_root(){
assertEquals "run_env_as_root command" "$(cat $STDOUTF)"
}
function test_run_env_as_fakeroot_with_namespace(){
assertCommandSuccess cli -u -f
assertEquals "run_env_as_fakeroot_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess cli --user-namespace --fakeroot
assertEquals "run_env_as_fakeroot_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess cli -u -f -p "-b arg"
assertEquals "run_env_as_fakeroot_with_namespace(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess cli -u -f -p "-b arg" -- command -kv
assertEquals "run_env_as_fakeroot_with_namespace(-b arg,command -kv)" "$(cat $STDOUTF)"
assertCommandSuccess cli -u -f command --as
assertEquals "run_env_as_fakeroot_with_namespace(,command --as)" "$(cat $STDOUTF)"
}
function test_run_env_as_user_with_namespace(){
assertCommandSuccess cli -u
assertEquals "run_env_as_user_with_namespace(,)" "$(cat $STDOUTF)"
assertCommandSuccess cli -u -p "-b arg"
assertEquals "run_env_as_user_with_namespace(-b arg,)" "$(cat $STDOUTF)"
assertCommandSuccess cli -u -p "-b arg" -- command -ll
assertEquals "run_env_as_user_with_namespace(-b arg,command -ll)" "$(cat $STDOUTF)"
assertCommandSuccess cli -u command -ls
assertEquals "run_env_as_user_with_namespace(,command -ls)" "$(cat $STDOUTF)"
}
function test_check_cli(){
assertCommandFail cli -b -h
assertCommandFail cli -b -c

View file

@ -100,6 +100,16 @@ function test_mkdir(){
MKDIR=false LD_EXEC=false assertCommandFail mkdir_cmd -p new_dir/new_dir
}
function test_zgrep(){
ZGREP=echo assertCommandSuccess zgrep_cmd new_file
assertEquals "new_file" "$(cat $STDOUTF)"
ZGREP=false assertCommandSuccess zgrep_cmd new_file
assertEquals "ld_exec ${JUNEST_HOME}/usr/bin/false new_file" "$(cat $STDOUTF)"
ZGREP=false LD_EXEC=false assertCommandFail zgrep_cmd new_file
}
function test_chroot(){
CHROOT=echo assertCommandSuccess chroot_cmd root
assertEquals "root" "$(cat $STDOUTF)"

View file

@ -0,0 +1,48 @@
#!/bin/bash
JUNEST_ROOT=$(readlink -f $(dirname $0)/../..)
source "$JUNEST_ROOT/tests/utils/utils.sh"
source "$JUNEST_ROOT/lib/utils/utils.sh"
source "$JUNEST_ROOT/lib/core/common.sh"
source "$JUNEST_ROOT/lib/core/namespace.sh"
# Disable the exiterr
set +e
function oneTimeSetUp(){
setUpUnitTests
}
function setUp(){
cwdSetUp
}
function tearDown(){
cwdTearDown
}
function test_is_user_namespace_enabled_no_config_file(){
CONFIG_PROC_FILE="blah"
CONFIG_BOOT_FILE="blah"
assertCommandFailOnStatus $NOT_EXISTING_FILE _is_user_namespace_enabled
}
function test_is_user_namespace_enabled_no_config(){
touch config
gzip config
CONFIG_PROC_FILE="config.gz"
CONFIG_BOOT_FILE="blah"
assertCommandFailOnStatus $NO_CONFIG_FOUND _is_user_namespace_enabled
}
function test_is_user_namespace_enabled_with_config(){
echo "CONFIG_USER_NS=y" > config
gzip config
CONFIG_PROC_FILE="config.gz"
CONFIG_BOOT_FILE="blah"
assertCommandSuccess _is_user_namespace_enabled
}
source $JUNEST_ROOT/tests/utils/shunit2