case vcFEATURE_VSTAT : return ver >= 0x00020103;
case vcFEATURE_PPTAG : return conf & VC_VCI_PPTAG;
case vcFEATURE_SPACES : return conf & VC_VCI_SPACES;
- case vcFEATURE_PIDSPACE : return ver >= 0x00020304 || ver >= 0x00020201;
+ case vcFEATURE_PIVOT_ROOT : return ver >= 0x00020304;
+ case vcFEATURE_PIDSPACE : return ver >= 0x00020305;
default : assert(false);
}
DECL(MIGRATE), DECL(NAMESPACE), DECL(SCHED), DECL(VINFO),
DECL(VHI), DECL(VSHELPER0), DECL(VSHELPER), DECL(VWAIT),
DECL(VNET), DECL(VSTAT), DECL(PPTAG), DECL(PIDSPACE),
- DECL(SPACES), DECL(PERSISTENT),
+ DECL(SPACES), DECL(PERSISTENT),DECL(PIVOT_ROOT),
};
bool
vcFEATURE_VSHELPER0, vcFEATURE_VSHELPER, vcFEATURE_VWAIT,
vcFEATURE_VNET, vcFEATURE_VSTAT, vcFEATURE_PPTAG,
vcFEATURE_PIDSPACE, vcFEATURE_SPACES, vcFEATURE_PERSISTENT,
+ vcFEATURE_PIVOT_ROOT,
}
vcFeatureSet;
declare -a OPTS_VCONTEXT_CREATE=()
declare -a OPTS_VCONTEXT_MIGRATE=()
declare -a OPTS_VCONTEXT_ENTER=()
+OPT_VCONTEXT_CHROOT=--chroot
declare -a OPTS_VATTRIBUTE=( --flag fakeinit )
declare -a OPTS_VSCHED=()
declare -a OPTS_ENV=()
isAvoidNamespace "$vdir" || {
USE_VNAMESPACE=1
CHCONTEXT_FLAG_OPTS=( "${CHCONTEXT_FLAG_OPTS[@]}" --flag namespace )
+ ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+ OPT_VCONTEXT_CHROOT=--pivot-root
}
}
local ns_opt=$2
local vdir=$1/vdir
local mtab_src
+ local extra_opt=
+ local real_vdir
test -e "$cfgdir"/fstab -o \
-e "$cfgdir"/fstab.local -o \
isNamespaceCleanup "$cfgdir" && \
_namespaceCleanup "$cfgdir"
+ real_vdir=$(getPhysicalDir "$vdir")
+ ! $_VSERVER_INFO - FEATURE PIVOT_ROOT || \
+ extra_opt=,shared
isAvoidNamespace "$cfgdir" || \
- $_SECURE_MOUNT --rbind -n -o dev "$vdir" "/"
+ $_SECURE_MOUNT --rbind -n -o dev$extra_opt "$vdir" "$real_vdir"
}
function _umountVserverInternal
$_VATTRIBUTE --set "${OPTS_VATTRIBUTE[@]}" -- \
$_SAVE_CTXINFO "$VSERVER_DIR" \
$_ENV -i "${OPTS_ENV[@]}" \
- $_VCONTEXT --migrate-self --endsetup --chroot $SILENT_OPT \
+ $_VCONTEXT --migrate-self --endsetup $OPT_VCONTEXT_CHROOT $SILENT_OPT \
"${OPTS_VCONTEXT_MIGRATE[@]}" "${OPTS_VCONTEXT_ENTER[@]}" -- \
"${INITCMD_START[@]}"
else
"${CHBIND_CMD[@]}" \
"$_VSPACE" --enter "$S_CONTEXT" "${OPTS_VSPACE[@]}" -- \
"$_VTAG" --migrate "${OPTS_VTAG_ENTER[@]}" --silent -- \
- $_VCONTEXT $SILENT_OPT --migrate --chroot --xid "$S_CONTEXT" -- \
+ $_VCONTEXT $SILENT_OPT --migrate $OPT_VCONTEXT_CHROOT --xid "$S_CONTEXT" -- \
"${INITCMD_STOP[@]}" || fail=1
else
"${IONICE_CMD[@]}" \
${USE_VNAMESPACE:+$_VNAMESPACE --enter "$S_CONTEXT" -- } \
$_VSPACE --enter "$S_CONTEXT" "${OPTS_VSPACE[@]}" -- \
$_VTAG --migrate "${OPTS_VTAG_ENTER[@]}" --silent -- \
- $_VCONTEXT $SILENT_OPT --migrate --chroot \
+ $_VCONTEXT $SILENT_OPT --migrate $OPT_VCONTEXT_CHROOT \
--xid "$S_CONTEXT" --uid "$user" "${OPTS_VCONTEXT_ENTER[@]}" -- \
"$@"
else
"${CHBIND_CMD[@]}" \
$_EXEC_ULIMIT "$VSERVER_DIR/ulimits" \
$_VTAG --create "${OPTS_VTAG_CREATE[@]}" --silent -- \
- $_VSPACE --new "${OPTS_VSPACE[@]}" -- \
+ $_VSPACE --new "${OPTS_VSPACE[@]}" ${USE_VNAMESPACE:+--mount --fs} -- \
$_VCONTEXT --create "${OPTS_VCONTEXT_CREATE[@]}" -- \
- $_VSPACE --set "${OPTS_VSPACE[@]}" -- \
- $_VUNAME --xid self --dir "$VSERVER_DIR"/uts --missingok -- \
+ $_VSPACE --set "${OPTS_VSPACE[@]}" ${USE_VNAMESPACE:+--mount --fs} -- \
+ $_VUNAME --xid self --dir "$VSERVER_DIR"/uts --missingok -- \
$_VUNAME --xid self --set -t context="$VSERVER_DIR" -- \
- $_VCONTEXT --migrate-self --endsetup --chroot $SILENT_OPT -- \
+ $_VCONTEXT --migrate-self --endsetup $OPT_VCONTEXT_CHROOT $SILENT_OPT -- \
"$@"
fi
else
{ "noauto", 0, 0, XFLAG_NOAUTO, false },
{ "user", 0, 0, 0, false },
{ "nouser", 0, 0, 0, false },
+ { "rec", MS_REC, MS_REC, 0, false },
+ { "unbindable", MS_UNBINDABLE, MS_UNBINDABLE, 0, false },
+ { "private", MS_PRIVATE, MS_PRIVATE, 0, false },
+ { "slave", MS_SLAVE, MS_SLAVE, 0, false },
+ { "shared", MS_SHARED, MS_SHARED, 0, false },
};
int wrapper_exit_code = 1;
#include "lib/internal.h"
#include "lib_internal/jail.h"
#include "lib_internal/sys_personality.h"
+#include "lib_internal/sys_unshare.h"
#include <vserver.h>
#include <getopt.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
+#include <sys/mount.h>
#include <linux/personality.h>
#define CMD_PERSTYPE 0x400e
#define CMD_PERSFLAG 0x400f
#define CMD_VLOGIN 0x4010
+#define CMD_PIVOT_ROOT 0x4011
struct option const
{ "personality-type", required_argument, 0, CMD_PERSTYPE },
{ "personality-flags", required_argument, 0, CMD_PERSFLAG },
{ "vlogin", no_argument, 0, CMD_VLOGIN },
+ { "pivot-root", no_argument, 0, CMD_PIVOT_ROOT },
#if 1
{ "fakeinit", no_argument, 0, CMD_INITPID }, // compatibility
#endif
uint_least32_t personality_type;
int verbosity;
bool do_chroot;
+ bool do_pivot_root;
char const * uid;
xid_t xid;
char const * sync_sock;
else if (args->do_migrate) Evc_enter_namespace(xid, CLONE_NEWNS|CLONE_FS, 0);
}
}
+ else if (args->do_pivot_root) {
+ if (vc_enter_namespace(xid, CLONE_NEWNS | CLONE_FS, 1) == -1) {
+ bool existed = false;
+ if (sys_unshare(CLONE_NEWNS) == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "unshare(NEWNS)");
+ return wrapper_exit_code;
+ }
+ if (mkdir("./.oldroot", 0700) == -1) {
+ if (errno == EEXIST)
+ existed = true;
+ else {
+ perror(ENSC_WRAPPERS_PREFIX "mkdir()");
+ return wrapper_exit_code;
+ }
+ }
+ if (pivot_root(".", "./.oldroot") == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "pivot_root()");
+ return wrapper_exit_code;
+ }
+ if (umount2("/.oldroot", MNT_DETACH) == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "umount2()");
+ return wrapper_exit_code;
+ }
+ if (!existed && rmdir("/.oldroot") == -1) {
+ perror(ENSC_WRAPPERS_PREFIX "rmdir()");
+ return wrapper_exit_code;
+ }
+ Evc_set_namespace(xid, CLONE_NEWNS | CLONE_FS, 1);
+ }
+ }
setFlags(args, xid);
case CMD_VLOGIN : args.do_vlogin = true; break;
case CMD_INITPID : args.is_initpid = true; break;
case CMD_CHROOT : args.do_chroot = true; break;
+ case CMD_PIVOT_ROOT : args.do_pivot_root = true; break;
case CMD_NAMESPACE : args.set_namespace = true; break;
case CMD_SILENTEXIST : args.is_silentexist = true; break;
case CMD_SYNCSOCK : args.sync_sock = optarg; break;