From 9e91084ef21e24292680e946d54647a6630cf79f Mon Sep 17 00:00:00 2001 From: Jason Mehring Date: Tue, 14 Oct 2014 12:02:12 -0400 Subject: [PATCH] Debian Wheezy template addition and refactoring to allow Whonix TEMPLATE_FLAVOR --- .../netvm-whitelisted-appmenus.list | 1 + appmenus_wheezy/vm-whitelisted-appmenus.list | 1 + appmenus_wheezy/whitelisted-appmenus.list | 1 + cleanup_image | 1 + prepare_image | 77 ++- qubeize_image | 105 ++-- scripts_debian/00_prepare.sh | 48 +- scripts_debian/01_install_core.sh | 32 +- scripts_debian/02_install_groups.sh | 192 ++++++-- scripts_debian/04_install_qubes.sh | 238 +++++++--- scripts_debian/09_cleanup.sh | 23 +- scripts_debian/NOTES | 5 + .../02_install_groups_packages_installed.sh | 1 + .../04_install_qubes_post.sh | 1 + .../99_custom_configuration.sh | 20 + .../etc/udev/rules.d/99-qubes-whonix.rules | 2 + .../usr/lib/whonix/replace-ips | 60 +++ .../usr/lib/whonix/setup-ip | 38 ++ .../02_install_groups_packages_installed.sh | 1 + .../04_install_qubes_post.sh | 1 + .../99_custom_configuration.sh | 12 + .../02_install_groups_packages_installed.sh | 216 +++++++++ .../04_install_qubes_post.sh | 55 +++ .../etc/udev/rules.d/98-kexec.rules | 4 + .../etc/udev/rules.d/xen-backend.rules | 16 + .../extra-qubes-files/etc/xen/scripts/blktap | 94 ++++ .../extra-qubes-files/etc/xen/scripts/block | 354 ++++++++++++++ .../etc/xen/scripts/block-common.sh | 125 +++++ .../etc/xen/scripts/block-enbd | 27 ++ .../etc/xen/scripts/block-nbd | 27 ++ .../etc/xen/scripts/external-device-migrate | 98 ++++ .../etc/xen/scripts/hotplugpath.sh | 10 + .../etc/xen/scripts/locking.sh | 110 +++++ .../etc/xen/scripts/logging.sh | 22 + .../etc/xen/scripts/network-bridge | 337 +++++++++++++ .../etc/xen/scripts/network-nat | 124 +++++ .../etc/xen/scripts/network-route | 28 ++ .../etc/xen/scripts/vif-bridge | 108 +++++ .../etc/xen/scripts/vif-common.sh | 190 ++++++++ .../extra-qubes-files/etc/xen/scripts/vif-nat | 192 ++++++++ .../etc/xen/scripts/vif-route | 56 +++ .../etc/xen/scripts/vif-route-qubes | 65 +++ .../etc/xen/scripts/vif-setup | 9 + .../extra-qubes-files/etc/xen/scripts/vif2 | 46 ++ .../extra-qubes-files/etc/xen/scripts/vscsi | 22 + .../extra-qubes-files/etc/xen/scripts/vtpm | 22 + .../etc/xen/scripts/vtpm-common.sh | 448 ++++++++++++++++++ .../etc/xen/scripts/vtpm-delete | 18 + .../etc/xen/scripts/vtpm-hotplug-common.sh | 35 ++ .../etc/xen/scripts/vtpm-impl | 208 ++++++++ .../etc/xen/scripts/vtpm-migration.sh | 19 + .../etc/xen/scripts/xen-hotplug-cleanup | 45 ++ .../etc/xen/scripts/xen-hotplug-common.sh | 102 ++++ .../etc/xen/scripts/xen-network-common.sh | 141 ++++++ .../etc/xen/scripts/xen-script-common.sh | 44 ++ .../debian-jessie-archive-keyring.gpg} | Bin .../keys/debian-wheezy-archive-keyring.gpg | Bin 0 -> 3569 bytes scripts_debian/packages.list | 10 +- scripts_debian/packages_jessie.list | 9 + scripts_debian/packages_wheezy.list | 9 + .../packages_wheezy_whonix-gateway.list | 1 + .../packages_wheezy_whonix-workstation.list | 1 + scripts_debian/packages_wheezy_whonix.list | 29 ++ scripts_debian/vars.sh | 108 +++++ umount.sh | 60 +++ 65 files changed, 4324 insertions(+), 180 deletions(-) create mode 100644 appmenus_wheezy/netvm-whitelisted-appmenus.list create mode 100644 appmenus_wheezy/vm-whitelisted-appmenus.list create mode 100644 appmenus_wheezy/whitelisted-appmenus.list create mode 100644 scripts_debian/NOTES create mode 120000 scripts_debian/custom_wheezy_whonix-gateway/02_install_groups_packages_installed.sh create mode 120000 scripts_debian/custom_wheezy_whonix-gateway/04_install_qubes_post.sh create mode 100755 scripts_debian/custom_wheezy_whonix-gateway/99_custom_configuration.sh create mode 100644 scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/etc/udev/rules.d/99-qubes-whonix.rules create mode 100755 scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/replace-ips create mode 100755 scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/setup-ip create mode 120000 scripts_debian/custom_wheezy_whonix-workstation/02_install_groups_packages_installed.sh create mode 120000 scripts_debian/custom_wheezy_whonix-workstation/04_install_qubes_post.sh create mode 100755 scripts_debian/custom_wheezy_whonix-workstation/99_custom_configuration.sh create mode 100755 scripts_debian/custom_wheezy_whonix/02_install_groups_packages_installed.sh create mode 100755 scripts_debian/custom_wheezy_whonix/04_install_qubes_post.sh create mode 100644 scripts_debian/extra-qubes-files/etc/udev/rules.d/98-kexec.rules create mode 100644 scripts_debian/extra-qubes-files/etc/udev/rules.d/xen-backend.rules create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/blktap create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/block create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/block-common.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/block-enbd create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/block-nbd create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/external-device-migrate create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/hotplugpath.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/locking.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/logging.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/network-bridge create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/network-nat create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/network-route create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif-bridge create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif-common.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif-nat create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route-qubes create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif-setup create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vif2 create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vscsi create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-common.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-delete create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-hotplug-common.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-impl create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-migration.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-cleanup create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-common.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/xen-network-common.sh create mode 100755 scripts_debian/extra-qubes-files/etc/xen/scripts/xen-script-common.sh rename scripts_debian/{debian-archive-keyring.gpg => keys/debian-jessie-archive-keyring.gpg} (100%) create mode 100644 scripts_debian/keys/debian-wheezy-archive-keyring.gpg mode change 100644 => 120000 scripts_debian/packages.list create mode 100644 scripts_debian/packages_jessie.list create mode 100644 scripts_debian/packages_wheezy.list create mode 120000 scripts_debian/packages_wheezy_whonix-gateway.list create mode 120000 scripts_debian/packages_wheezy_whonix-workstation.list create mode 100644 scripts_debian/packages_wheezy_whonix.list create mode 100755 umount.sh diff --git a/appmenus_wheezy/netvm-whitelisted-appmenus.list b/appmenus_wheezy/netvm-whitelisted-appmenus.list new file mode 100644 index 0000000..4b744f7 --- /dev/null +++ b/appmenus_wheezy/netvm-whitelisted-appmenus.list @@ -0,0 +1 @@ +gnome-terminal.desktop diff --git a/appmenus_wheezy/vm-whitelisted-appmenus.list b/appmenus_wheezy/vm-whitelisted-appmenus.list new file mode 100644 index 0000000..4b744f7 --- /dev/null +++ b/appmenus_wheezy/vm-whitelisted-appmenus.list @@ -0,0 +1 @@ +gnome-terminal.desktop diff --git a/appmenus_wheezy/whitelisted-appmenus.list b/appmenus_wheezy/whitelisted-appmenus.list new file mode 100644 index 0000000..4b744f7 --- /dev/null +++ b/appmenus_wheezy/whitelisted-appmenus.list @@ -0,0 +1 @@ +gnome-terminal.desktop diff --git a/cleanup_image b/cleanup_image index 3716593..195f1ac 100755 --- a/cleanup_image +++ b/cleanup_image @@ -20,6 +20,7 @@ ls -als $IMG mount -o loop $IMG mnt || exit 1 export INSTALLDIR=`pwd`/mnt/ +echo "--> Cleaning up image file..." $SCRIPTSDIR/09_cleanup.sh echo "--> Compacting image file..." diff --git a/prepare_image b/prepare_image index c6b7a62..7763464 100755 --- a/prepare_image +++ b/prepare_image @@ -1,6 +1,10 @@ -#!/bin/sh +#!/bin/bash +#XXX: use bash #!/bin/sh -export IMG=$1 +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +export IMG="$1" export LC_ALL=POSIX RETCODE=0 @@ -8,49 +12,70 @@ RETCODE=0 : ${DIST=fc14} . ./builder_setup >/dev/null +. ./umount.sh >/dev/null -set -e +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +else + set -e +fi if ! [ $# -eq 1 ]; then -echo "usage $0 " -exit + echo "usage $0 " + exit fi if [ "$VERBOSE" == "1" ]; then - export YUM_OPTS="$YUM_OPTS -q" + export YUM_OPTS="$YUM_OPTS -q" fi +# ------------------------------------------------------------------------------ +# Prepare for mount +# ------------------------------------------------------------------------------ echo "-> Preparing instalation of $DIST template..." -$SCRIPTSDIR/00_prepare.sh - -if [ -f $IMG ]; then - echo "-> Image file already exists, assuming *update*..." - mount -o loop $IMG mnt || exit 1 - export INSTALLDIR=`pwd`/mnt/ - trap "umount $INSTALLDIR" EXIT +"$SCRIPTSDIR/00_prepare.sh" + +# ------------------------------------------------------------------------------ +# Mount image and install core OS +# ------------------------------------------------------------------------------ +if [ -f "$IMG" ]; then + echo "-> Image file already exists, assuming *update*..." + mount -o loop "$IMG" mnt || exit 1 + export INSTALLDIR="`pwd`/mnt/" + trap "umount_image ${INSTALLDIR::-1}" EXIT + + # XXX: Temp; just for debugging + if ! [ -f "$INSTALLDIR/tmp/.prepared_debootstrap" ]; then + "$SCRIPTSDIR/01_install_core.sh" + fi else + echo "-> Initializing empty image..." + truncate -s 10G "$IMG" || exit 1 - echo "-> Initializing empty image..." - truncate -s 10G $IMG || exit 1 + echo "-> Creating filesystem..." + mkfs.ext4 -q -F "$IMG" || exit 1 - echo "-> Creating filesystem..." - mkfs.ext4 -q -F $IMG || exit 1 + mkdir -p mnt + mount -o loop "$IMG" mnt || exit 1 - mkdir -p mnt - mount -o loop $IMG mnt || exit 1 + export INSTALLDIR="`pwd`/mnt/" + trap "umount_image ${INSTALLDIR::-1}" EXIT - export INSTALLDIR=`pwd`/mnt/ - - trap "umount $INSTALLDIR" EXIT - - $SCRIPTSDIR/01_install_core.sh + "$SCRIPTSDIR/01_install_core.sh" fi +# ------------------------------------------------------------------------------ +# Install package groups +# ------------------------------------------------------------------------------ echo "-> Installing package groups..." -$SCRIPTSDIR/02_install_groups.sh +"$SCRIPTSDIR/02_install_groups.sh" +# ------------------------------------------------------------------------------ +# Cleanup +# ------------------------------------------------------------------------------ trap - EXIT + echo "-> Unmounting prepared_image..." -sudo umount $INSTALLDIR +umount_image "$INSTALLDIR" || : exit $RETCODE diff --git a/qubeize_image b/qubeize_image index 6f0e563..9c4b049 100755 --- a/qubeize_image +++ b/qubeize_image @@ -1,81 +1,105 @@ #!/bin/sh -export CLEANIMG=$1 -export NAME=$2 +# ------------------------------------------------------------------------------ +# Configurations and Conditionals +# ------------------------------------------------------------------------------ +export CLEANIMG="$1" +export NAME="$2" export LC_ALL=POSIX . ./builder_setup >/dev/null +. ./umount.sh >/dev/null -set -e +#set -e +set -x if [ $# -eq 0 ]; then -echo "usage $0 " -exit + echo "usage $0 " + exit fi -if [ x$CLEANIMG = x ]; then -echo "Image file not specified!" -exit 1 +if [ "x$CLEANIMG" = x ]; then + echo "Image file not specified!" + exit 1 fi -if [ x$NAME = x ]; then -echo "Name not given!" -exit 1 +if [ "x$NAME" = x ]; then + echo "Name not given!" + exit 1 fi ID=$(id -ur) if [ $ID != 0 ] ; then - echo "This script should be run as root user." - exit 1 + echo "This script should be run as root user." + exit 1 fi if [ "$VERBOSE" == "1" ]; then - export YUM_OPTS="$YUM_OPTS -q" + export YUM_OPTS="$YUM_OPTS -q" fi +# ------------------------------------------------------------------------------ +# Cleanup function +# ------------------------------------------------------------------------------ function cleanup() { - if grep -q " $PWD/mnt/proc " /proc/mounts; then - umount mnt/proc - fi - if grep -q " $PWD/mnt " /proc/mounts; then - umount mnt - fi + umount_image "$PWD/mnt" || : } - trap cleanup ERR -export IMG=qubeized_images/$NAME-root.img -echo "--> Copying $CLEANIMG to $IMG..." -cp $CLEANIMG $IMG || exit 1 +# ------------------------------------------------------------------------------ +# Mount qubeized_image +# ------------------------------------------------------------------------------ +# NEW: continue installation from last point if UPDATE="false" +# if UPDATE does not exist (keep it backwards compatible for fedora script) +# - OR - +# update="true", copy over prepared image as normal -echo "--> Mounting $IMG" +export IMG="qubeized_images/$NAME-root.img" + +[ "$UPDATE" ] && UPDATE=$(echo $UPDATE | awk '{print tolower($0)}') +if [ "$IMG" -nt "$CLEANIMG" -a "$UPDATE" == "false" ]; then + echo "--> Using original $IMG... (UPDATE=false and qubized_image is newer than prepared_image)" +else + echo "--> Copying $CLEANIMG to $IMG..." + cp "$CLEANIMG" "$IMG" || exit 1 +fi +echo "--> Mounting $IMG" mkdir -p mnt -mount -o loop $IMG mnt || exit 1 +mount -o loop "$IMG" mnt || exit 1 export INSTALLDIR=mnt -$SCRIPTSDIR/04_install_qubes.sh || { umount $INSTALLDIR; exit 1; } +# ------------------------------------------------------------------------------ +# Run qubeize script +# ------------------------------------------------------------------------------ +"$SCRIPTSDIR/04_install_qubes.sh" || { umount "$INSTALLDIR"; exit 1; } +# ------------------------------------------------------------------------------ +# Create App Menus +# ------------------------------------------------------------------------------ echo "--> Copying the Apps Menu shortcuts..." -export APPSORIG=qubeized_images/$NAME-apps.orig -export APPSTEMPL=qubeized_images/$NAME-apps.templates -mkdir -p $APPSORIG -cp -r $(pwd)/mnt/usr/share/applications/* $APPSORIG +export APPSORIG="qubeized_images/$NAME-apps.orig" +export APPSTEMPL="qubeized_images/$NAME-apps.templates" +mkdir -p "$APPSORIG" +cp -r "$(pwd)"/mnt/usr/share/applications/* "$APPSORIG" echo "--> Creating the Apps Menu templates..." -./create_apps_templates.sh $APPSORIG $APPSTEMPL +"./create_apps_templates.sh" "$APPSORIG" "$APPSTEMPL" echo "--> Choosing appmenus whitelists..." rm -f appmenus if [ -d "appmenus_${DIST}_${TEMPLATE_FLAVOR}" ]; then - ln -s "appmenus_${DIST}_${TEMPLATE_FLAVOR}" appmenus + ln -s "appmenus_${DIST}_${TEMPLATE_FLAVOR}" appmenus elif [ -d "appmenus_$DIST" ]; then - ln -s "appmenus_$DIST" appmenus + ln -s "appmenus_$DIST" appmenus else - ln -s "appmenus_generic" appmenus + ln -s "appmenus_generic" appmenus fi +# ------------------------------------------------------------------------------ +# Link directories so they can be mounted +# ------------------------------------------------------------------------------ echo "--> Linking /home to /rw/home..." mv mnt/home mnt/home.orig ln -sf /rw/home mnt/home @@ -85,14 +109,17 @@ mv mnt/usr/local mnt/usr/local.orig ln -sf /rw/usrlocal mnt/usr/local if [ -e mnt/etc/sysconfig/i18n ]; then - echo "--> Setting up default locale..." - echo LC_CTYPE=en_US.UTF-8 > mnt/etc/sysconfig/i18n + echo "--> Setting up default locale..." + echo LC_CTYPE=en_US.UTF-8 > mnt/etc/sysconfig/i18n fi +# ------------------------------------------------------------------------------ +# Finsh - unmount image +# ------------------------------------------------------------------------------ echo "--> Unmounting $IMG" -umount mnt +cleanup echo "Qubeized image stored at: $IMG" echo "Reducing image size (calling cleanup_image)..." -./cleanup_image $IMG +./cleanup_image "$IMG" diff --git a/scripts_debian/00_prepare.sh b/scripts_debian/00_prepare.sh index c530c0f..4e895cf 100755 --- a/scripts_debian/00_prepare.sh +++ b/scripts_debian/00_prepare.sh @@ -1,5 +1,49 @@ -#!/bin/sh -x +#!/bin/bash -x # vim: set ts=4 sw=4 sts=4 et : -# This script does nothing now. +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +. ./umount.sh >/dev/null + +INSTALLDIR="`pwd`/mnt/" +umount_image "${INSTALLDIR::-1}" || : + +# ------------------------------------------------------------------------------ +# Set debug display +# ------------------------------------------------------------------------------ +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +else + set -e +fi + +# ------------------------------------------------------------------------------ +# Execute any custom pre configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "pre" + +# ------------------------------------------------------------------------------ +# Force overwrite of an existing image for now if debootstrap did not seem to complete... +# ------------------------------------------------------------------------------ +if [ -f "$IMG" ]; then + mount -o loop "$IMG" "$INSTALLDIR" || exit 1 + + # Assume a failed debootstrap installation if .prepare_debootstrap does not exist + if ! [ -f "$INSTALLDIR/tmp/.prepared_debootstrap" ]; then + echo "-> Failed Image file $IMG already exists, deleting..." + rm -f "$IMG" + # Allow qubes to be updated + elif [ -f "$INSTALLDIR/tmp/.prepared_qubes" ]; then + rm "$INSTALLDIR/tmp/.prepared_qubes" + fi + + # Umount image; don't fail if its already umounted + umount_image "${INSTALLDIR::-1}" || : +fi + +# ------------------------------------------------------------------------------ +# Execute any custom post configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "post" diff --git a/scripts_debian/01_install_core.sh b/scripts_debian/01_install_core.sh index a384d23..65f29b6 100755 --- a/scripts_debian/01_install_core.sh +++ b/scripts_debian/01_install_core.sh @@ -1,11 +1,35 @@ #!/bin/sh # vim: set ts=4 sw=4 sts=4 et : +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ . $SCRIPTSDIR/vars.sh -echo "-> Installing base debian system" +set -e +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +fi -COMPONENTS="" debootstrap --arch=amd64 --include=ncurses-term \ - --components=main --keyring=${SCRIPTSDIR}/debian-archive-keyring.gpg \ - $DEBIANVERSION "$INSTALLDIR" http://http.debian.net/debian || { echo "Debootstrap failed!"; exit 1; } +# ------------------------------------------------------------------------------ +# Execute any custom pre configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "pre" + +# ------------------------------------------------------------------------------ +# Install base debian system +# ------------------------------------------------------------------------------ +if ! [ -f "$INSTALLDIR/tmp/.prepared_debootstrap" ]; then + echo "-> Installing base ${DEBIANVERSION} system" + COMPONENTS="" debootstrap --arch=amd64 --include=ncurses-term \ + --components=main --keyring="${SCRIPTSDIR}/keys/debian-${DEBIANVERSION}-archive-keyring.gpg" \ + "$DEBIANVERSION" "$INSTALLDIR" "$DEBIAN_MIRROR" || { echo "Debootstrap failed!"; exit 1; } + chroot "$INSTALLDIR" chmod 0666 "/dev/null" + touch "$INSTALLDIR/tmp/.prepared_debootstrap" +fi + +# ------------------------------------------------------------------------------ +# Execute any custom post configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "post" diff --git a/scripts_debian/02_install_groups.sh b/scripts_debian/02_install_groups.sh index f8ef9c2..d87cc40 100755 --- a/scripts_debian/02_install_groups.sh +++ b/scripts_debian/02_install_groups.sh @@ -1,57 +1,177 @@ #!/bin/sh # vim: set ts=4 sw=4 sts=4 et : +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +set -x + . $SCRIPTSDIR/vars.sh +. ./umount.sh >/dev/null + +# ------------------------------------------------------------------------------ +# If .prepared_debootstrap has not been completed, don't continue +# ------------------------------------------------------------------------------ +if ! [ -f "$INSTALLDIR/tmp/.prepared_debootstrap" ]; then + echo "--> prepared_debootstrap installataion has not completed!... Exiting" + exit 1 +fi + +# ------------------------------------------------------------------------------ +# Mount system mount points +# ------------------------------------------------------------------------------ +for fs in /dev /dev/pts /proc /sys /run; do mount -B $fs "$INSTALLDIR/$fs"; done + +# ------------------------------------------------------------------------------ +# Execute any custom pre configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "pre" -# Set up a temporary policy-rc.d to prevent apt from starting services -# on package installation -cat > $BUILDCHROOT/usr/sbin/policy-rc.d < Install groups error and umount" + rm -f "$INSTALLDIR/usr/sbin/policy-rc.d" + umount_image "$INSTALLDIR" || : + exit 1 + } + trap error ERR + trap error EXIT + + # ------------------------------------------------------------------------------ + # Set up a temporary policy-rc.d to prevent apt from starting services + # on package installation + # ------------------------------------------------------------------------------ + cat > "$INSTALLDIR/usr/sbin/policy-rc.d" < Adding debian-security repository." - # security.debian.org only makes sense for stable/wheezy - echo "deb http://security.debian.org/ ${DEBIANVERSION}/updates main" \ - >> "$INSTALLDIR/etc/apt/sources.list" - echo "deb-src http://security.debian.org/ ${DEBIANVERSION}/updates main" \ - >> "$INSTALLDIR/etc/apt/sources.list" - - echo "--> Installing systemd" - # sysvinit gives problems with qubes initramfs, we depend on systemd - # for now. Apt *really* doesn't want to replace sysvinit in wheezy. - # For jessie and newer, sysvinit is provided by sysvinit-core which - # is not an essential package. - echo 'Yes, do as I say!' | chroot $INSTALLDIR apt-get -y \ - --force-yes install systemd-sysv -else # testing/unstable - echo "--> Installing systemd" - chroot $INSTALLDIR apt-get -y install systemd-sysv -fi + source="deb http://security.debian.org ${DEBIANVERSION}/updates main" + if ! grep -r -q "$source" "$INSTALLDIR/etc/apt/sources.list"*; then + touch "$INSTALLDIR/etc/apt/sources.list" + echo "$source" >> "$INSTALLDIR/etc/apt/sources.list" + fi + source="deb-src http://security.debian.org ${DEBIANVERSION}/updates main" + if ! grep -r -q "$source" "$INSTALLDIR/etc/apt/sources.list"*; then + touch "$INSTALLDIR/etc/apt/sources.list" + echo "$source" >> "$INSTALLDIR/etc/apt/sources.list" + fi -chroot $INSTALLDIR systemctl set-default multi-user.target + # ------------------------------------------------------------------------------ + # Upgrade system + # ------------------------------------------------------------------------------ + echo "--> Upgrading system" + chroot "$INSTALLDIR" apt-get update + DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + chroot "$INSTALLDIR" apt-get -y --force-yes dist-upgrade -echo "--> Upgrading system" -chroot $INSTALLDIR apt-get update -chroot $INSTALLDIR apt-get -y upgrade - -echo "--> Setting keyboard layout" -chroot $INSTALLDIR debconf-set-selections < Setting keyboard layout" + chroot "$INSTALLDIR" debconf-set-selections < Installing extra packages" -xargs chroot $INSTALLDIR apt-get -y install < $SCRIPTSDIR/packages.list + # ------------------------------------------------------------------------------ + # Install extra packages in script_$DEBIANVERSION/packages.list file + # ------------------------------------------------------------------------------ + if [ -n "${TEMPLATE_FLAVOR}" ]; then + PKGLISTFILE="$SCRIPTSDIR/packages_${DIST}_${TEMPLATE_FLAVOR}.list" + if ! [ -r "${PKGLISTFILE}" ]; then + echo "ERROR: ${PKGLISTFILE} does not exists!" + exit 1 + fi + elif [ -r "$SCRIPTSDIR/packages_${DIST}.list" ]; then + PKGLISTFILE="$SCRIPTSDIR/packages_${DIST}.list" + else + PKGLISTFILE="$SCRIPTSDIR/packages.list" + fi + + echo "--> Installing extra packages" + DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + xargs chroot $INSTALLDIR apt-get -y --force-yes install < "$PKGLISTFILE" + + # ------------------------------------------------------------------------------ + # Execute any custom configuration scripts after file packages installed + # (Whonix needs dependancies installed before installation) + # ------------------------------------------------------------------------------ + customStep "$0" "packages_installed" + + # ------------------------------------------------------------------------------ + # Install systemd + # ------------------------------------------------------------------------------ + # - sysvinit gives problems with qubes initramfs, we depend on systemd + # for now. Apt *really* doesn't want to replace sysvinit in wheezy. + # For jessie and newer, sysvinit is provided by sysvinit-core which + # is not an essential package. + # ------------------------------------------------------------------------------ + echo "--> Installing systemd for wheezy ($DEBIANVERSION)" + echo 'Yes, do as I say!' | DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + chroot "$INSTALLDIR" apt-get -y --force-yes remove sysvinit + + # Prevent sysvinit from being re-installed + echo "--> Preventing sysvinit re-installation" + chroot "$INSTALLDIR" apt-mark hold sysvinit + + chroot "$INSTALLDIR" apt-get update + DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + chroot "$INSTALLDIR" apt-get -y --force-yes install systemd-sysv + + # ------------------------------------------------------------------------------ + # Set multu-user.target as the default target (runlevel 3) + # ------------------------------------------------------------------------------ + #chroot "$INSTALLDIR" systemctl set-default multi-user.target + chroot "$INSTALLDIR" rm -f /etc/systemd/system/default.target + chroot "$INSTALLDIR" ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target + + # ------------------------------------------------------------------------------ + # Qubes is now being built with some SID packages; grab backport for wheezy + # ------------------------------------------------------------------------------ + if [ "$DEBIANVERSION" == "wheezy" ]; then + echo "--> Adding wheezy backports repository." + source="deb http://http.debian.net/debian wheezy-backports main" + if ! grep -r -q "$source" "$INSTALLDIR/etc/apt/sources.list"*; then + touch "$INSTALLDIR/etc/apt/sources.list" + echo "$source" >> "$INSTALLDIR/etc/apt/sources.list" + fi + chroot $INSTALLDIR apt-get update + DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + chroot $INSTALLDIR apt-get -y --force-yes -t wheezy-backports install init-system-helpers + fi + + # ------------------------------------------------------------------------------ + # Cleanup + # ------------------------------------------------------------------------------ + # Remove temporary policy layer so services can start normally in the + # deployed template. + rm -f "$INSTALLDIR/usr/sbin/policy-rc.d" + touch "$INSTALLDIR/tmp/.prepared_groups" + trap - ERR EXIT + trap + + # Kill all processes and umount all mounts within $INSTALLDIR, + # but not $INSTALLDIR itself (extra '/' prevents $INSTALLDIR from being + # umounted itself) + umount_image "$INSTALLDIR/" || : +fi -# Remove temporary policy layer so services can start normally in the -# deployed template. -rm -f $BUILDCHROOT/usr/sbin/policy-rc.d +# ------------------------------------------------------------------------------ +# Execute any custom post configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "post" diff --git a/scripts_debian/04_install_qubes.sh b/scripts_debian/04_install_qubes.sh index 8f05f57..f29612f 100755 --- a/scripts_debian/04_install_qubes.sh +++ b/scripts_debian/04_install_qubes.sh @@ -1,45 +1,103 @@ #!/bin/sh # vim: set ts=4 sw=4 sts=4 et : +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +set -x + +# ------------------------------------------------------------------------------ +# Source external scripts +# ------------------------------------------------------------------------------ . $SCRIPTSDIR/vars.sh +. ./umount.sh >/dev/null + +# ------------------------------------------------------------------------------ +# If .prepared_groups has not been completed, don't continue +# ------------------------------------------------------------------------------ +if ! [ -f "$INSTALLDIR/tmp/.prepared_groups" ]; then + echo "--> prepared_groups installataion has not completed!... Exiting" + exit 1 +fi -# Set up a temporary policy-rc.d to prevent apt from starting services -# on package installation -cat > $INSTALLCHROOT/usr/sbin/policy-rc.d < Installing qbues modules" + + # -------------------------------------------------------------------------- + # Set up a temporary policy-rc.d to prevent apt from starting services + # on package installation + # -------------------------------------------------------------------------- + cat > "$INSTALLCHROOT/usr/sbin/policy-rc.d" < Generate locales" -echo "en_US.UTF-8 UTF-8" >> $INSTALLDIR/etc/locale.gen -chroot $INSTALLDIR locale-gen -chroot $INSTALLDIR update-locale LANG=en_US.UTF-8 - -echo "--> Updating template fstab file..." -cat >> $INSTALLDIR/etc/fstab < Generate locales" + echo "en_US.UTF-8 UTF-8" >> "$INSTALLDIR/etc/locale.gen" + chroot "$INSTALLDIR" locale-gen + chroot "$INSTALLDIR" update-locale LANG=en_US.UTF-8 + + # -------------------------------------------------------------------------- + # Update /etc/fstab + # -------------------------------------------------------------------------- + echo "--> Updating template fstab file..." + cat >> "$INSTALLDIR/etc/fstab" < Installing qubes packages" -export CUSTOMREPO="$PWD/yum_repo_qubes/$DIST" - -if ! [ -e $CACHEDIR/repo-secring.gpg ]; then - mkdir -p $CACHEDIR - gpg --gen-key --batch < Installing qubes packages" + export CUSTOMREPO="$PWD/yum_repo_qubes/$DIST" + + # -------------------------------------------------------------------------- + # Install keyrings + # -------------------------------------------------------------------------- + if ! [ -e "$CACHEDIR/repo-secring.gpg" ]; then + mkdir -p "$CACHEDIR" + gpg --gen-key --batch < $INSTALLDIR/etc/apt/sources.list.d/qubes-builder.list < "$INSTALLDIR/etc/apt/sources.list.d/qubes-builder.list" <> $INSTALLDIR/etc/modules - -sed -i -e '/^mesg n/d' $INSTALLDIR/root/.profile + # -------------------------------------------------------------------------- + # Update system; exit is not successful + # -------------------------------------------------------------------------- + chroot "$INSTALLDIR" apt-get update || { umount "$INSTALLDIR/tmp/qubes_repo"; exit 1; } + + # -------------------------------------------------------------------------- + # Install Qubes packages + # -------------------------------------------------------------------------- + DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + chroot "$INSTALLDIR" apt-get -y --force-yes install `cat $SCRIPTSDIR/packages_qubes.list` || \ + { umount "$INSTALLDIR/tmp/qubes_repo"; exit 1; } + + # -------------------------------------------------------------------------- + # Remove Quebes repo from sources.list.d + # -------------------------------------------------------------------------- + rm -f "$INSTALLDIR"/etc/apt/sources.list.d/qubes*.list + umount "$INSTALLDIR/tmp/qubes_repo" + rm -f "$INSTALLDIR/etc/apt/sources.list.d/qubes-builder.list" + chroot "$INSTALLDIR" apt-get update || exit 1 + + # -------------------------------------------------------------------------- + # Remove temporary policy layer so services can start normally in the + # deployed template. + # -------------------------------------------------------------------------- + rm -f "$BUILDCHROOT/usr/sbin/policy-rc.d" + + # -------------------------------------------------------------------------- + # Qubes needs a user named 'user' + # -------------------------------------------------------------------------- + if chroot "$INSTALLDIR" id -u 'user' >/dev/null 2>&1; then + : + else + chroot "$INSTALLDIR" groupadd -f user + chroot "$INSTALLDIR" useradd -g user -G dialout,cdrom,floppy,sudo,audio,dip,video,plugdev -m -s /bin/bash user + fi + + # -------------------------------------------------------------------------- + # Modules setup + # -------------------------------------------------------------------------- + echo "xen_netfront" >> "$INSTALLDIR/etc/modules" + + # -------------------------------------------------------------------------- + # Remove `mesg` from root/.profile? + # -------------------------------------------------------------------------- + sed -i -e '/^mesg n/d' "$INSTALLDIR/root/.profile" + + # -------------------------------------------------------------------------- + # Need a xen log directory or xen scripts will fail + # -------------------------------------------------------------------------- + mkdir -p -m 0700 "$INSTALLDIR/var/log/xen" + + # -------------------------------------------------------------------------- + # Copy over any extra files that may be needed that are located in + # $SCRIPT_DIR/extra-qubes-files + # -------------------------------------------------------------------------- + echo "-> Copy extra files..." + copy_dirs "extra-qubes-files" + + touch "$INSTALLDIR/tmp/.prepared_qubes" +fi -# Kill any processes that might have been started by apt before unmounting -lsof $INSTALLDIR | tail -n +2 | awk '{print $2}' | xargs --no-run-if-empty kill +# ------------------------------------------------------------------------------ +# Execute any custom post configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "post" +# ------------------------------------------------------------------------------ +# Kill all processes and umount all mounts within $INSTALLDIR, but not +# $INSTALLDIR itself (extra '/' prevents $INSTALLDIR from being umounted itself) +# ------------------------------------------------------------------------------ +umount_image "$INSTALLDIR/" || : diff --git a/scripts_debian/09_cleanup.sh b/scripts_debian/09_cleanup.sh index 6e55efa..5411a9c 100755 --- a/scripts_debian/09_cleanup.sh +++ b/scripts_debian/09_cleanup.sh @@ -1,10 +1,27 @@ #!/bin/sh # vim: set ts=4 sw=4 sts=4 et : -rm -f $INSTALLDIR/var/cache/apt/archives/* +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +. $SCRIPTSDIR/vars.sh -rm -f $INSTALLDIR/etc/apt/sources.list.d/qubes-builder.list -rm -f $INSTALLDIR/etc/apt/trusted.gpg.d/qubes-builder.gpg +# ------------------------------------------------------------------------------ +# Execute any custom pre configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "pre" +# ------------------------------------------------------------------------------ +# Cleanup any left over files from installation +# ------------------------------------------------------------------------------ +rm -rf "INSTALLDIR/var/cache/apt/archives/*" +rm -f "$INSTALLDIR/etc/apt/sources.list.d/qubes-builder.list" +rm -f "$INSTALLDIR/etc/apt/trusted.gpg.d/qubes-builder.gpg" + +# XXX: Whats this for? rm -rf buildchroot +# ------------------------------------------------------------------------------ +# Execute any custom post configuration scripts +# ------------------------------------------------------------------------------ +customStep "$0" "post" diff --git a/scripts_debian/NOTES b/scripts_debian/NOTES new file mode 100644 index 0000000..e67480d --- /dev/null +++ b/scripts_debian/NOTES @@ -0,0 +1,5 @@ +NOTES +===== + +- move whonix install into step 01-pre! + that way we dont need to setup systemd 2 times! diff --git a/scripts_debian/custom_wheezy_whonix-gateway/02_install_groups_packages_installed.sh b/scripts_debian/custom_wheezy_whonix-gateway/02_install_groups_packages_installed.sh new file mode 120000 index 0000000..282b083 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-gateway/02_install_groups_packages_installed.sh @@ -0,0 +1 @@ +../custom_wheezy_whonix/02_install_groups_packages_installed.sh \ No newline at end of file diff --git a/scripts_debian/custom_wheezy_whonix-gateway/04_install_qubes_post.sh b/scripts_debian/custom_wheezy_whonix-gateway/04_install_qubes_post.sh new file mode 120000 index 0000000..2ee5337 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-gateway/04_install_qubes_post.sh @@ -0,0 +1 @@ +../custom_wheezy_whonix/04_install_qubes_post.sh \ No newline at end of file diff --git a/scripts_debian/custom_wheezy_whonix-gateway/99_custom_configuration.sh b/scripts_debian/custom_wheezy_whonix-gateway/99_custom_configuration.sh new file mode 100755 index 0000000..6474734 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-gateway/99_custom_configuration.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# vim: set ts=4 sw=4 sts=4 et : + +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +. $SCRIPTSDIR/vars.sh +. ./umount.sh >/dev/null + +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +fi + +if [ -f "$INSTALLDIR/tmp/.prepared_whonix" -a ! -f "$INSTALLDIR/tmp/.prepared_whonix_custom_configurations" ]; then + # -------------------------------------------------------------------------- + # Install Custom Configurations + # -------------------------------------------------------------------------- + echo "10.152.152.10" > "$INSTALLDIR/etc/whonix-netvm-gateway" + touch "$INSTALLDIR/tmp/.prepared_whonix_custom_configurations" +fi diff --git a/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/etc/udev/rules.d/99-qubes-whonix.rules b/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/etc/udev/rules.d/99-qubes-whonix.rules new file mode 100644 index 0000000..fe68663 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/etc/udev/rules.d/99-qubes-whonix.rules @@ -0,0 +1,2 @@ + +SUBSYSTEMS=="xen", KERNEL=="eth*", ACTION=="add", RUN+="/usr/lib/whonix/setup-ip" diff --git a/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/replace-ips b/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/replace-ips new file mode 100755 index 0000000..dbf7022 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/replace-ips @@ -0,0 +1,60 @@ +#!/bin/bash + +# Search though files and updates IP address to current qubes-netvm-gateway address on startup +# of eth0 + + +DIRS="/usr/lib/leaktest-workstation/simple_ping.py \ + /usr/lib/whonixcheck/preparation \ + /usr/share/anon-kde-streamiso/share/config/kioslaverc \ + /usr/bin/whonix_firewall \ + /etc/whonix_firewall.d/30_default \ + /usr/lib/anon-shared-helper-scripts/tor_bootstrap_check.bsh \ + /usr/bin/uwt \ + /etc/uwt.d/30_uwt_default \ + /usr/share/tor/tor-service-defaults-torrc.anondist \ + /usr/bin/update-torbrowser \ + /etc/network/interfaces.whonix \ + /etc/resolv.conf.anondist \ + /etc/sdwdate.d/31_anon_dist_stream_isolation_plugin \ + /etc/rinetd.conf.anondist \ + /etc/network/interfaces.whonix \ + /usr/share/anon-torchat/.torchat/torchat.ini" + +# $1 = space delimited files +function replace_ips() +{ + IP=$2 + LAST_IP=$3 + + if ! [ "$LAST_IP" == "$IP" ]; then + for file in $1; do + if [ -f "$file" ]; then + #find / -xdev -type f -print0 | xargs -0r file | grep 'ASCII text' | awk -F: '{print $1}' | \ + # xargs -d'\n' -r sed -i "s/$LAST_IP/$IP/g" + #find / -xdev -type f -print0 | xargs -0r file | grep 'ASCII text' | awk -F: '{print $1}' | \ + # xargs -d'\n' -r sed -i "s/$LAST_IP_PART./$IP_PART./g" + sed -i "s/$LAST_IP/$IP/g" "$file" + fi + done + echo "$IP" > /etc/whonix-netvm-gateway + service tor restart + fi +} + +IP=`xenstore-read qubes-netvm-gateway` +IP_PART=$(echo $IP | cut -f 1,2,3 -d".") +LAST_IP="$(cat /etc/whonix-netvm-gateway)" +LAST_IP_PART=$(echo $LAST_IP | cut -f 1,2,3 -d".") +replace_ips "$DIRS" $IP $LAST_IP + +# Do again; checking for original 10.152.152.10 incase of update +LAST_IP=10.152.152.10 +LAST_IP_PART=$(echo $LAST_IP | cut -f 1,2,3 -d".") +replace_ips "$DIRS" $IP $LAST_IP + +# Do again; checking for original 10.152.152.11 incase of update +LAST_IP=10.152.152.11 +LAST_IP_PART=$(echo $LAST_IP | cut -f 1,2,3 -d".") +replace_ips "$DIRS" $IP $LAST_IP + diff --git a/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/setup-ip b/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/setup-ip new file mode 100755 index 0000000..0c4fbec --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-gateway/extra-whonix-files/usr/lib/whonix/setup-ip @@ -0,0 +1,38 @@ +#!/bin/sh + +if [ -x /usr/sbin/xenstore-read ]; then + XENSTORE_READ="/usr/sbin/xenstore-read" +else + XENSTORE_READ="/usr/bin/xenstore-read" +fi + +# Create a dummy eth1 interface so tor can bind to it if there +# are no DOMU virtual machines connected at the moment +INTERFACE="eth1" +/sbin/ip link add $INTERFACE type dummy + +# Now, assign it the netvm-gateway IP address +ip=$($XENSTORE_READ qubes-netvm-gateway 2> /dev/null) +if [ x$ip != x ]; then + netmask=$($XENSTORE_READ qubes-netvm-netmask) + gateway=$($XENSTORE_READ qubes-netvm-gateway) + /sbin/ifconfig $INTERFACE $ip netmask 255.255.255.255 + /sbin/ifconfig $INTERFACE up + /sbin/ethtool -K $INTERFACE sg off + /sbin/ethtool -K $INTERFACE tx off +fi + +# Replace IP addresses in known configuration files / scripts to +# currently discovered one +/usr/lib/whonix/replace-ips + +# Make sure we have correct nameserver set +echo "nameserver 127.0.0.1" > /etc/resolv.conf + +# Make sure hostname is correct +/bin/hostname -b host + +# Start Whonix Firewall +export INT_IF="vif+" +export INT_TIF="vif+" +/usr/bin/whonix_firewall diff --git a/scripts_debian/custom_wheezy_whonix-workstation/02_install_groups_packages_installed.sh b/scripts_debian/custom_wheezy_whonix-workstation/02_install_groups_packages_installed.sh new file mode 120000 index 0000000..282b083 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-workstation/02_install_groups_packages_installed.sh @@ -0,0 +1 @@ +../custom_wheezy_whonix/02_install_groups_packages_installed.sh \ No newline at end of file diff --git a/scripts_debian/custom_wheezy_whonix-workstation/04_install_qubes_post.sh b/scripts_debian/custom_wheezy_whonix-workstation/04_install_qubes_post.sh new file mode 120000 index 0000000..2ee5337 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-workstation/04_install_qubes_post.sh @@ -0,0 +1 @@ +../custom_wheezy_whonix/04_install_qubes_post.sh \ No newline at end of file diff --git a/scripts_debian/custom_wheezy_whonix-workstation/99_custom_configuration.sh b/scripts_debian/custom_wheezy_whonix-workstation/99_custom_configuration.sh new file mode 100755 index 0000000..73ba84c --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix-workstation/99_custom_configuration.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# vim: set ts=4 sw=4 sts=4 et : + +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +. $SCRIPTSDIR/vars.sh +. ./umount.sh >/dev/null + +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +fi diff --git a/scripts_debian/custom_wheezy_whonix/02_install_groups_packages_installed.sh b/scripts_debian/custom_wheezy_whonix/02_install_groups_packages_installed.sh new file mode 100755 index 0000000..2223777 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix/02_install_groups_packages_installed.sh @@ -0,0 +1,216 @@ +#!/bin/bash +# vim: set ts=4 sw=4 sts=4 et : + +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +. $SCRIPTSDIR/vars.sh +. ./umount.sh >/dev/null + +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +fi + +# ------------------------------------------------------------------------------ +# chroot Whonix build script (Make sure set -e is not set) +# ------------------------------------------------------------------------------ +read -r -d '' WHONIX_BUILD_SCRIPT <<'EOF' +#!/bin/bash + +################################################################################ +# Pre Fixups +sudo mkdir -p /boot/grub2 +sudo touch /boot/grub2/grub.cfg +sudo mkdir -p /boot/grub +sudo touch /boot/grub/grub.cfg +sudo mkdir --parents --mode=g+rw "/tmp/uwt" + +# Whonix seems to re-install sysvinit even though there is a hold +# on the package. Things seem to work anyway. BUT hopfully the +# hold on grub* don't get removed +sudo apt-mark hold sysvinit +sudo apt-mark hold grub-common grub-pc-bin grub2-common + +# Whonix expects haveged to be started +sudo /etc/init.d/haveged start + +################################################################################ +# Whonix installation +export WHONIX_BUILD_UNATTENDED_PKG_INSTALL="1" + +pushd ~/Whonix +sudo ~/Whonix/whonix_build \ + --build $1 \ + --64bit-linux \ + --current-sources \ + --enable-whonix-apt-repository \ + --whonix-apt-repository-distribution $2 \ + --install-to-root \ + --skip-verifiable \ + --minimal-report \ + --skip-sanity-tests || { exit 1; } +popd + +################################################################################ +# Post Fixups + +pushd /etc/network +sudo rm -f interfaces +sudo ln -s interfaces.backup interfaces +popd + +pushd /etc +sudo rm -f resolv.conf +sudo ln -s resolv.conf.backup resolv.conf +popd + +sudo update-rc.d network-manager disable +sudo update-rc.d spice-vdagent disable +sudo update-rc.d swap-file-creator disable +sudo update-rc.d whonix-initializer disable + +# Fake that initializer was already run +sudo mkdir -p /root/.whonix +sudo touch /root/.whonix/first_run_initializer.done + +# Prevent whonixcheck error +sudo su -c 'echo WHONIXCHECK_NO_EXIT_ON_UNSUPPORTED_VIRTUALIZER=\"1\" >> /etc/whonix.d/30_whonixcheck_default' + +# Ensure umask set in /etc/login.defs is used (022) +sudo su -c 'echo "session optional pam_umask.so" >> /etc/pam.d/common-session' + +sudo touch "/tmp/.prepared_whonix" + +EOF + + +# ------------------------------------------------------------------------------ +# chroot Whonix fix script (Make sure set -e is not set) +# Run ../whonix_fix when whonix gives grub-pc error +# ------------------------------------------------------------------------------ +# TODO: Do something in whonix build to automatically run fixups and +# ignore certain errors +read -r -d '' WHONIX_FIX_SCRIPT <<'EOF' +DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ + sudo apt-get -y --force-yes remove grub-common grub-pc-bin grub2-common +sudo apt-mark hold grub-common grub-pc-bin grub2-common +EOF + + +# ------------------------------------------------------------------------------ +# Set defualts for apt not to install recommended or extra packages +# ------------------------------------------------------------------------------ +read -r -d '' WHONIX_APT_PREFERENCES <<'EOF' +Acquire::Languages "none"; +APT::Install-Recommends "false"; +APT::Install-Suggests "false"; +Dpkg::Options "--force-confold"; +EOF + +# ------------------------------------------------------------------------------ +# Cleanup function +# ------------------------------------------------------------------------------ +function error() { + echo "--> Whonix error; umounting $INSTALLDIR to prevent further writes" + umount_image "$INSTALLDIR" || : + exit 1 +} +trap error ERR +trap error EXIT + +# ------------------------------------------------------------------------------ +# Mount devices, etc required for Whonix installation +# ------------------------------------------------------------------------------ +if ! [ -f "$INSTALLDIR/tmp/.prepared_whonix" ]; then + echo "-> Installing whonix system" + + # -------------------------------------------------------------------------- + # Whonix system config dependancies + # -------------------------------------------------------------------------- + #/usr/sbin/grub-probe: error: cannot find a device for / (is /dev mounted?) + #cannot stat `/boot/grub/grub.cfg': No such file or directory + + # Qubes needs a user named 'user' + if chroot "$INSTALLDIR" id -u 'user' >/dev/null 2>&1; then + : + else + chroot "$INSTALLDIR" groupadd -f user + chroot "$INSTALLDIR" useradd -g user -G dialout,cdrom,floppy,sudo,audio,dip,video,plugdev -m -s /bin/bash user + fi + + # Change hostname to 'host' + echo "host" > "$INSTALLDIR/etc/hostname" + chroot "$INSTALLDIR" sed -i "s/localhost/host/g" /etc/hosts + + if ! [ -f "$INSTALLDIR/etc/sudoers.d/qubes" ]; then + cp -p /etc/sudoers.d/qubes "$INSTALLDIR/etc/sudoers.d/qubes" + fi + + # -------------------------------------------------------------------------- + # Install Whonix system + # -------------------------------------------------------------------------- + if ! [ -d "$INSTALLDIR/home/user/Whonix" ]; then + echo "-> Installing Whonix build environment..." + chroot "$INSTALLDIR" su user -c 'mkdir /home/user/Whonix' + fi + + if [ -d "$INSTALLDIR/home/user/Whonix" ]; then + mount --bind "../Whonix" "$INSTALLDIR/home/user/Whonix" + echo "-> Building Whonix..." + + # Install apt-get preferences + echo "$WHONIX_APT_PREFERENCE" > "$INSTALLDIR/etc/apt/apt.conf.d/99whonix" + chmod 0644 "$INSTALLDIR/etc/apt/apt.conf.d/99whonix" + + # Install Whonix fix script + echo "$WHONIX_FIX_SCRIPT" > "$INSTALLDIR/home/user/whonix_fix" + chmod 0755 "$INSTALLDIR/home/user/whonix_fix" + + # Install Whonix build scripts + echo "$WHONIX_BUILD_SCRIPT" > "$INSTALLDIR/home/user/whonix_build" + chmod 0755 "$INSTALLDIR/home/user/whonix_build" + + if [ "${TEMPLATE_FLAVOR}" == "whonix-gateway" ]; then + BUILD_TYPE="--torgateway" + elif [ "${TEMPLATE_FLAVOR}" == "whonix-workstation" ]; then + BUILD_TYPE="--torworkstation" + else + echo "Incorrent Whonix type \"${TEMPLATE_FLAVOR}\" selected. Not building Whonix modules" + echo "You need to set TEMPLATE_FLAVOR environment variable to either" + echo "whonix-gateway OR whonix-workstation" + exit 1 + fi + + chroot "$INSTALLDIR" su user -c "cd ~; ./whonix_build $BUILD_TYPE $DIST" || { exit 1; } + fi +fi + +# ------------------------------------------------------------------------------ +# Execute any custom configuration scripts +# ------------------------------------------------------------------------------ +customStep "99_custom_configuration.sh" + +# XXX: Why do I need to move them out of the way? Lets try keeping them +# in place (modify post script too) +# ------------------------------------------------------------------------------ +# Move Whonix sources out of way +# ------------------------------------------------------------------------------ +#if [ -L "$INSTALLDIR/etc/apt/sources.list.d" ]; then +# mv "$INSTALLDIR/etc/apt/sources.list.d" "$INSTALLDIR/etc/apt/sources.list.d.qubes" +# mkdir -p "$INSTALLDIR/etc/apt/sources.list.d" +# cp -p "$INSTALLDIR/etc/apt/sources.list.d.qubes/debian.list" "$INSTALLDIR/etc/apt/sources.list.d" +#fi + +# ------------------------------------------------------------------------------ +# Bring back original apt-get for installation of Qubues +# ------------------------------------------------------------------------------ +if [ -L "$INSTALLDIR/usr/bin/apt-get" ]; then + rm "$INSTALLDIR/usr/bin/apt-get" + chroot "$INSTALLDIR" su -c "cd /usr/bin/; ln -s apt-get.anondist-orig apt-get" +fi + +# ------------------------------------------------------------------------------ +# Leave cleanup to calling function +# ------------------------------------------------------------------------------ +trap - ERR EXIT +trap diff --git a/scripts_debian/custom_wheezy_whonix/04_install_qubes_post.sh b/scripts_debian/custom_wheezy_whonix/04_install_qubes_post.sh new file mode 100755 index 0000000..11f4193 --- /dev/null +++ b/scripts_debian/custom_wheezy_whonix/04_install_qubes_post.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# vim: set ts=4 sw=4 sts=4 et : + +# +# Whonix Post Install Steps (after qubes install) +# + +# ------------------------------------------------------------------------------ +# Configurations +# ------------------------------------------------------------------------------ +. $SCRIPTSDIR/vars.sh + +if [ "$VERBOSE" -ge 2 -o "$DEBUG" == "1" ]; then + set -x +fi + +# ------------------------------------------------------------------------------ +# Restore Whonix apt-get +# ------------------------------------------------------------------------------ +if [ -L "$INSTALLDIR/usr/bin/apt-get" ]; then + rm "$INSTALLDIR/usr/bin/apt-get" + chroot "$INSTALLDIR" su -c "cd /usr/bin/; ln -s apt-get.anondist apt-get" +fi + +# ------------------------------------------------------------------------------ +# Restore Whonix sources +# ------------------------------------------------------------------------------ +#if [ -L "$INSTALLDIR/etc/apt/sources.list.d" ]; then +# rm -rf "$INSTALLDIR/etc/apt/sources.list.d" +# mv "$INSTALLDIR/etc/apt/sources.list.d.qubes" "$INSTALLDIR/etc/apt/sources.list.d" +#fi + +# ------------------------------------------------------------------------------ +# Restore whonix resolv.conf +# ------------------------------------------------------------------------------ +if [ -L "$INSTALLDIR/etc/resolv.conf" ]; then + pushd "$INSTALLDIR/etc" + sudo rm -f resolv.conf + sudo ln -s resolv.conf.anondist resolv.conf + popd +fi + +# ------------------------------------------------------------------------------ +# Copy over any extra files +# ------------------------------------------------------------------------------ +echo "-> Copy extra files..." +copy_dirs "extra-whonix-files" + +# ------------------------------------------------------------------------------ +# Cleanup Whonix Installation +# ------------------------------------------------------------------------------ +rm -rf "$INSTALLDIR"/home/user/Whonix +rm -rf "$INSTALLDIR"/home/user/whonix_binary +rm -f "$INSTALLDIR"/home/user/whonix_fix +rm -f "$INSTALLDIR"/home/user/whonix_build diff --git a/scripts_debian/extra-qubes-files/etc/udev/rules.d/98-kexec.rules b/scripts_debian/extra-qubes-files/etc/udev/rules.d/98-kexec.rules new file mode 100644 index 0000000..8c742dd --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/udev/rules.d/98-kexec.rules @@ -0,0 +1,4 @@ +SUBSYSTEM=="cpu", ACTION=="online", PROGRAM="/bin/systemctl try-restart kdump.service" +SUBSYSTEM=="cpu", ACTION=="offline", PROGRAM="/bin/systemctl try-restart kdump.service" +SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/systemctl try-restart kdump.service" +SUBSYSTEM=="memory", ACTION=="remove", PROGRAM="/bin/systemctl try-restart kdump.service" diff --git a/scripts_debian/extra-qubes-files/etc/udev/rules.d/xen-backend.rules b/scripts_debian/extra-qubes-files/etc/udev/rules.d/xen-backend.rules new file mode 100644 index 0000000..40f2658 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/udev/rules.d/xen-backend.rules @@ -0,0 +1,16 @@ +SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap $env{ACTION}" +SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}" +SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}" +SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 $env{ACTION}" +SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif" +SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="offline", RUN+="/etc/xen/scripts/vif-setup offline type_if=vif" +SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}" +SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup" +KERNEL=="evtchn", NAME="xen/%k" +SUBSYSTEM=="xen", KERNEL=="blktap[0-9]*", NAME="xen/%k", MODE="0600" +SUBSYSTEM=="blktap2", KERNEL=="blktap[0-9]*", NAME="xen/blktap-2/%k", MODE="0600" +KERNEL=="blktap-control", NAME="xen/blktap-2/control", MODE="0600" +KERNEL=="gntdev", NAME="xen/%k", MODE="0600" +KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600" +KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600" +SUBSYSTEM=="net", KERNEL=="tap*", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/blktap b/scripts_debian/extra-qubes-files/etc/xen/scripts/blktap new file mode 100755 index 0000000..cd30a38 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/blktap @@ -0,0 +1,94 @@ +#!/bin/bash + +# Copyright (c) 2005, XenSource Ltd. + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" +. "$dir/block-common.sh" + +findCommand "$@" + +## +# check_blktap_sharing file mode +# +# Perform the sharing check for the given blktap and mode. +# +check_blktap_sharing() +{ + local file="$1" + local mode="$2" + + local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE" + for dom in $(xenstore-list "$base_path") + do + for dev in $(xenstore-list "$base_path/$dom") + do + params=$(xenstore_read_default "$base_path/$dom/$dev/params" "" | cut -d: -f2) + if [ "$file" = "$params" ] + then + + if [ "$mode" = 'w' ] + then + if ! same_vm "$dom" + then + echo 'guest' + return + fi + else + local m=$(xenstore_read_default "$base_path/$dom/$dev/mode" "") + m=$(canonicalise_mode "$m") + + if [ "$m" = 'w' ] + then + if ! same_vm "$dom" + then + echo 'guest' + return + fi + fi + fi + fi + done + done + + echo 'ok' +} + + +t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING') +if [ -n "$t" ] +then + p=$(xenstore_read "$XENBUS_PATH/params") + p=${p#tapdisk:} + # if we have a ':', chew from head including : + if echo $p | grep -q \: + then + p=${p#*:} + fi +fi +# some versions of readlink cannot be passed a regular file +if [ -L "$p" ]; then + file=$(readlink -f "$p") || fatal "$p link does not exist." +else + file="$p" +fi + +if [ "$command" = 'add' ] +then + [ -e "$file" ] || { fatal $file does not exist; } + + FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id") + FRONTEND_UUID=$(xenstore_read "/local/domain/$FRONTEND_ID/vm") + mode=$(xenstore_read "$XENBUS_PATH/mode") + mode=$(canonicalise_mode "$mode") + + if [ "$mode" != '!' ] + then + result=$(check_blktap_sharing "$file" "$mode") + [ "$result" = 'ok' ] || ebusy "$file already in use by other domain" + fi + + success +fi + +exit 0 diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/block b/scripts_debian/extra-qubes-files/etc/xen/scripts/block new file mode 100755 index 0000000..7266a78 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/block @@ -0,0 +1,354 @@ +#!/bin/bash + +dir=$(dirname "$0") +. "$dir/block-common.sh" + +HOTPLUG_STORE="/var/run/xen-hotplug/${XENBUS_PATH//\//-}" + +expand_dev() { + local dev + case $1 in + /*) + dev=$1 + ;; + *) + dev=/dev/$1 + ;; + esac + echo -n $dev +} + +find_free_loopback_helper() { + local next_devnum=0 + local busy_devnum + while read busy_devnum; do + if [ "$next_devnum" != "$busy_devnum" ]; then + break + fi + let next_devnum=$next_devnum+1 + done + echo "/dev/loop${next_devnum}" +} + +# Not all distros have "losetup -f" +find_free_loopback_dev() { + local loopdev + loopdev=$(losetup -a | sed -e 's+^/dev/loop++' -e 's/:.*//' | find_free_loopback_helper) + if [ -n "$loopdev" ] && [ -b "$loopdev" ]; then + echo "$loopdev" + fi +} + +## +# check_sharing device mode +# +# Check whether the device requested is already in use. To use the device in +# read-only mode, it may be in use in read-only mode, but may not be in use in +# read-write anywhere at all. To use the device in read-write mode, it must +# not be in use anywhere at all. +# +# Prints one of +# +# 'local': the device may not be used because it is mounted in the current +# (i.e. the privileged domain) in a way incompatible with the +# requested mode; +# 'guest': the device may not be used because it already mounted by a guest +# in a way incompatible with the requested mode; or +# 'ok': the device may be used. +# +check_sharing() +{ + local dev="$1" + local mode="$2" + + local devmm=$(device_major_minor "$dev") + local file + + if [ "$mode" = 'w' ] + then + toskip="^$" + else + toskip="^[^ ]* [^ ]* [^ ]* ro[, ]" + fi + + for file in $(cat /proc/mounts | grep -v "$toskip" | cut -f 1 -d ' ') + do + if [ -e "$file" ] + then + local d=$(device_major_minor "$file") + + if [ "$d" = "$devmm" ] + then + echo 'local' + return + fi + fi + done + + local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE" + for dom in $(xenstore-list "$base_path") + do + for dev in $(xenstore-list "$base_path/$dom") + do + d=$(xenstore_read_default "$base_path/$dom/$dev/physical-device" "") + + if [ "$d" = "$devmm" ] + then + if [ "$mode" = 'w' ] + then + if ! same_vm $dom + then + echo 'guest' + return + fi + else + local m=$(xenstore_read_default "$base_path/$dom/$dev/mode" "") + m=$(canonicalise_mode "$m") + + if [ "$m" = 'w' ] + then + if ! same_vm $dom + then + echo 'guest' + return + fi + fi + fi + fi + done + done + + echo 'ok' +} + + +## +# check_device_sharing dev mode +# +# Perform the sharing check for the given physical device and mode. +# +check_device_sharing() +{ + local dev="$1" + local mode=$(canonicalise_mode "$2") + local result + + if [ "x$mode" = 'x!' ] + then + return 0 + fi + + result=$(check_sharing "$dev" "$mode") + + if [ "$result" != 'ok' ] + then + do_ebusy "Device $dev is mounted " "$mode" "$result" + fi +} + + +## +# check_device_sharing file dev mode +# +# Perform the sharing check for the given file mounted through the given +# loopback interface, in the given mode. +# +check_file_sharing() +{ + local file="$1" + local dev="$2" + local mode="$3" + + result=$(check_sharing "$dev" "$mode") + + if [ "$result" != 'ok' ] + then + do_ebusy "File $file is loopback-mounted through $dev, +which is mounted " "$mode" "$result" + fi +} + + +## +# do_ebusy prefix mode result +# +# Helper function for check_device_sharing check_file_sharing, calling ebusy +# with an error message constructed from the given prefix, mode, and result +# from a call to check_sharing. +# +do_ebusy() +{ + local prefix="$1" + local mode="$2" + local result="$3" + + if [ "$result" = 'guest' ] + then + dom='a guest ' + when='now' + else + dom='the privileged ' + when='by a guest' + fi + + if [ "$mode" = 'w' ] + then + m1='' + m2='' + else + m1='read-write ' + m2='read-only ' + fi + + release_lock "block" + ebusy \ +"${prefix}${m1}in ${dom}domain, +and so cannot be mounted ${m2}${when}." +} + + +t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING') + +case "$command" in + add) + phys=$(xenstore_read_default "$XENBUS_PATH/physical-device" 'MISSING') + if [ "$phys" != 'MISSING' ] + then + # Depending upon the hotplug configuration, it is possible for this + # script to be called twice, so just bail. + exit 0 + fi + + if [ -n "$t" ] + then + p=$(xenstore_read "$XENBUS_PATH/params") + mode=$(xenstore_read "$XENBUS_PATH/mode") + echo $p > "$HOTPLUG_STORE-params" + echo $mode > "$HOTPLUG_STORE-mode" + echo $t > "$HOTPLUG_STORE-type" + fi + FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id") + FRONTEND_UUID=$(xenstore_read_default \ + "/local/domain/$FRONTEND_ID/vm" 'unknown') + + case $t in + phy) + dev=$(expand_dev $p) + + if [ -L "$dev" ] + then + dev=$(readlink -f "$dev") || fatal "$dev link does not exist." + fi + test -e "$dev" || fatal "$dev does not exist." + test -b "$dev" || fatal "$dev is not a block device." + + claim_lock "block" + check_device_sharing "$dev" "$mode" + write_dev "$dev" + release_lock "block" + exit 0 + ;; + + file) + # Canonicalise the file, for sharing check comparison, and the mode + # for ease of use here. + file=$(readlink -f "$p") || fatal "$p does not exist." + test -f "$file" || fatal "$file does not exist." + mode=$(canonicalise_mode "$mode") + + claim_lock "block" + + # Avoid a race with the remove if the path has been deleted, or + # otherwise changed from "InitWait" state e.g. due to a timeout + xenbus_state=$(xenstore_read_default "$XENBUS_PATH/state" 'unknown') + if [ "$xenbus_state" != '2' ] + then + release_lock "block" + fatal "Path closed or removed during hotplug add: $XENBUS_PATH state: $xenbus_state" + fi + + if [ "$mode" = 'w' ] && ! stat "$file" -c %A | grep -q w + then + release_lock "block" + ebusy \ +"File $file is read-only, and so I will not +mount it read-write in a guest domain." + fi + + if [ "x$mode" != 'x!' ] + then + inode=$(stat -c '%i' "$file") + dev=$(stat -c '%D' "$file") + if [ -z "$inode" ] || [ -z "$dev" ] + then + fatal "Unable to lookup $file: dev: $dev inode: $inode" + fi + + shared_list=$(losetup -j "$file" | head -n 1 | cut -d : -f 1) + for dev in "$shared_list" + do + if [ -n "$dev" ] + then + check_file_sharing "$file" "$dev" "$mode" + loopdev="$dev" + fi + done + fi + + if [ -z "$loopdev" ]; then + loopdev=$(losetup -f 2>/dev/null || find_free_loopback_dev) + if [ "$loopdev" = '' ] + then + release_lock "block" + fatal 'Failed to find an unused loop device' + fi + + if LANG=C losetup -h 2>&1 | grep read-only >/dev/null + then + roflag="-$mode"; roflag="${roflag#-w}"; roflag="${roflag#-!}" + else + roflag='' + fi + do_or_die losetup $roflag "$loopdev" "$file" + fi + xenstore_write "$XENBUS_PATH/node" "$loopdev" + echo $loopdev > "$HOTPLUG_STORE-node" + write_dev "$loopdev" + release_lock "block" + exit 0 + ;; + + "") + claim_lock "block" + success + release_lock "block" + ;; + esac + ;; + + remove) + t=$(cat $HOTPLUG_STORE-type) + case $t in + phy) + exit 0 + ;; + + file) + claim_lock "block" + node=$(cat "$HOTPLUG_STORE-node") + losetup -d "$node" + release_lock "block" + exit 0 + ;; + + "") + exit 0 + ;; + esac + ;; + +esac + +# If we've reached here, $t is neither phy nor file, so fire a helper script. +[ -x ${XEN_SCRIPT_DIR}/block-"$t" ] && \ + ${XEN_SCRIPT_DIR}/block-"$t" "$command" $node diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/block-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/block-common.sh new file mode 100755 index 0000000..cc374ef --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/block-common.sh @@ -0,0 +1,125 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" + +findCommand "$@" + +if [ "$command" != "add" ] && + [ "$command" != "remove" ] +then + log err "Invalid command: $command" + exit 1 +fi + + +XENBUS_PATH="${XENBUS_PATH:?}" + + +ebusy() +{ + xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \ + "$XENBUS_PATH/hotplug-status" busy + log err "$@" + exit 1 +} + + +## +# Print the given device's major and minor numbers, written in hex and +# separated by a colon. +device_major_minor() +{ + stat -L -c %t:%T "$1" +} + + +## +# Write physical-device = MM,mm to the store, where MM and mm are the major +# and minor numbers of device respectively. +# +# @param device The device from which major and minor numbers are read, which +# will be written into the store. +# +write_dev() { + local mm + + mm=$(device_major_minor "$1") + + if [ -z $mm ] + then + fatal "Backend device does not exist" + fi + + xenstore_write "$XENBUS_PATH/physical-device" "$mm" + + success +} + + +## +# canonicalise_mode mode +# +# Takes the given mode, which may be r, w, ro, rw, w!, or rw!, or variations +# thereof, and canonicalises them to one of +# +# 'r': perform checks for a new read-only mount; +# 'w': perform checks for a read-write mount; or +# '!': perform no checks at all. +# +canonicalise_mode() +{ + local mode="$1" + + if ! expr index "$mode" 'w' >/dev/null + then + echo 'r' + elif ! expr index "$mode" '!' >/dev/null + then + echo 'w' + else + echo '!' + fi +} + + +same_vm() +{ + local otherdom="$1" + # Note that othervm can be MISSING here, because Xend will be racing with + # the hotplug scripts -- the entries in /local/domain can be removed by + # Xend before the hotplug scripts have removed the entry in + # /local/domain/0/backend/. In this case, we want to pretend that the + # VM is the same as FRONTEND_UUID, because that way the 'sharing' will be + # allowed. + local othervm=$(xenstore_read_default "/local/domain/$otherdom/vm" \ + "$FRONTEND_UUID") + local target=$(xenstore_read_default "/local/domain/$FRONTEND_ID/target" \ + "-1") + local otarget=$(xenstore_read_default "/local/domain/$otherdom/target" \ + "-1") + local otvm=$(xenstore_read_default "/local/domain/$otarget/vm" \ + "-1") + otvm=${otvm%-1} + othervm=${othervm%-1} + local frontend_uuid=${FRONTEND_UUID%-1} + + [ "$frontend_uuid" = "$othervm" -o "$target" = "$otherdom" -o "$frontend_uuid" = "$otvm" ] +} + diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/block-enbd b/scripts_debian/extra-qubes-files/etc/xen/scripts/block-enbd new file mode 100755 index 0000000..67faa84 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/block-enbd @@ -0,0 +1,27 @@ +#!/bin/bash + +# Usage: block-enbd [bind server ctl_port |unbind node] +# +# The node argument to unbind is the name of the device node we are to +# unbind. +# +# This assumes you're running a correctly configured server at the other end! + +dir=$(dirname "$0") +. "$dir/block-common.sh" + +case "$command" in + add) + for dev in /dev/nd*; do + if nbd-client $2:$3 $dev; then + write_dev $dev + exit 0 + fi + done + exit 1 + ;; + remove) + nbd-client -d $2 + exit 0 + ;; +esac diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/block-nbd b/scripts_debian/extra-qubes-files/etc/xen/scripts/block-nbd new file mode 100755 index 0000000..b29b315 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/block-nbd @@ -0,0 +1,27 @@ +#!/bin/bash + +# Usage: block-nbd [bind server ctl_port |unbind node] +# +# The node argument to unbind is the name of the device node we are to +# unbind. +# +# This assumes you're running a correctly configured server at the other end! + +dir=$(dirname "$0") +. "$dir/block-common.sh" + +case "$command" in + add) + for dev in /dev/nbd*; do + if nbd-client $2 $3 $dev; then + write_dev $dev + exit 0 + fi + done + exit 1 + ;; + remove) + nbd-client -d $2 + exit 0 + ;; +esac diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/external-device-migrate b/scripts_debian/extra-qubes-files/etc/xen/scripts/external-device-migrate new file mode 100755 index 0000000..a411348 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/external-device-migrate @@ -0,0 +1,98 @@ +#!/bin/bash + +# Copyright (c) 2005 IBM Corporation +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +set -x + +# This script is called by XenD for migration of external devices +# It does not handle the migration of those devices itself, but +# passes the requests on to further applications +# It handles the low-level command line parsing and some of the +# synchronization + +dir=$(dirname "$0") +. "$dir/logging.sh" + + +function ext_dev_migrate_usage() { +cat < : n-th migration step +-host : the destination host +-domname : name of the domain that is migrating +-type : the type of device that is migrating +-subtype : the subtype of the device +-recover : indicates recovery request; an error + occurred during migration +-help : display this help screen +EOF +} + +# Parse the command line paramters. The following parameters must be +# passed as the first ones in the sequence: +# -step [required] +# -host [required] +# -domname [required] +# -type [required] +# -subtype [optional] +# -recover [optional] +# The remaining ones will be passed to the called function. +function evaluate_params() +{ + local step host domname typ recover filename func stype + stype="" + while [ $# -ge 1 ]; do + case "$1" in + -step) step=$2; shift; shift;; + -host) host=$2; shift; shift;; + -domname) domname=$2; shift; shift;; + -type) typ=$2; shift; shift;; + -subtype) stype=$2; shift; shift;; + -recover) recover=1; shift;; + -help) ext_dev_migrate_usage; exit 0;; + *) break;; + esac + done + + if [ "$step" = "" -o \ + "$host" = "" -o \ + "$typ" = "" -o \ + "$domname" = "" ]; then + echo "Error: Parameter(s) missing (-step/-host/-type/-domname)" 1>&2 + echo "" 1>&2 + echo "$0 -help for usage." 1>&2 + exit 1 + fi + + filename="$dir/$typ$stype-migration.sh" + if [ ! -r $filename ]; then + echo "Error: Could not find script '$filename'" + return + fi + . "$filename" + + if [ "$recover" = "1" ]; then + func="$typ"_recover + eval $func $host $domname $step $* + else + func="$typ"_migration_step + eval $func $host $domname $step $* + fi +} + +evaluate_params "$@" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/hotplugpath.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/hotplugpath.sh new file mode 100755 index 0000000..254b3e2 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/hotplugpath.sh @@ -0,0 +1,10 @@ +SBINDIR="/usr/sbin" +BINDIR="/usr/bin" +LIBEXEC="/usr/lib/xen/bin" +LIBDIR="/usr/lib64" +SHAREDIR="/usr/share" +PRIVATE_BINDIR="/usr/lib64/xen/bin" +XENFIRMWAREDIR="/usr/lib/xen/boot" +XEN_CONFIG_DIR="/etc/xen" +XEN_SCRIPT_DIR="/etc/xen/scripts" +XEN_LOCK_DIR="/var/lock" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/locking.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/locking.sh new file mode 100755 index 0000000..e233c47 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/locking.sh @@ -0,0 +1,110 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# Serialisation +# + +LOCK_SLEEPTIME=1 +LOCK_SPINNING_RETRIES=5 +LOCK_RETRIES=100 +LOCK_BASEDIR=/var/run/xen-hotplug + + +claim_lock() +{ + local lockdir="$LOCK_BASEDIR/$1" + mkdir -p "$LOCK_BASEDIR" + _claim_lock "$lockdir" +} + + +release_lock() +{ + _release_lock "$LOCK_BASEDIR/$1" +} + + +# This function will be redefined in xen-hotplug-common.sh. +sigerr() { + exit 1 +} + + +_claim_lock() +{ + local lockdir="$1" + local owner=$(_lock_owner "$lockdir") + local retries=0 + + while [ $retries -lt $LOCK_RETRIES ] + do + mkdir "$lockdir" 2>/dev/null && trap "_release_lock $lockdir; sigerr" ERR && + _update_lock_info "$lockdir" && return + + local new_owner=$(_lock_owner "$lockdir") + if [ "$new_owner" != "$owner" ] + then + owner="$new_owner" + retries=0 + else + local pid=$(echo $owner | cut -d : -f 1) + if [ -n "$pid" -a "$pid" != "unknown" -a ! -f "/proc/$pid/status" ] + then + _release_lock $lockdir + fi + fi + + if [ $retries -gt $LOCK_SPINNING_RETRIES ] + then + sleep $LOCK_SLEEPTIME + else + sleep 0 + fi + retries=$(($retries + 1)) + done + _steal_lock "$lockdir" +} + + +_release_lock() +{ + trap sigerr ERR + rm -rf "$1" 2>/dev/null || true +} + + +_steal_lock() +{ + local lockdir="$1" + local owner=$(cat "$lockdir/owner" 2>/dev/null || echo "unknown") + log err "Forced to steal lock on $lockdir from $owner!" + _release_lock "$lockdir" + _claim_lock "$lockdir" +} + + +_lock_owner() +{ + cat "$1/owner" 2>/dev/null || echo "unknown" +} + + +_update_lock_info() +{ + echo "$$: $0" >"$1/owner" +} diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/logging.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/logging.sh new file mode 100755 index 0000000..c1bc699 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/logging.sh @@ -0,0 +1,22 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +log() { + local level="$1" + shift + logger -p "daemon.$level" -- "$0:" "$@" || echo "$0 $@" >&2 +} diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/network-bridge b/scripts_debian/extra-qubes-files/etc/xen/scripts/network-bridge new file mode 100755 index 0000000..6f8475a --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/network-bridge @@ -0,0 +1,337 @@ +#!/bin/bash +#============================================================================ +# Default Xen network start/stop script. +# Xend calls a network script when it starts. +# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp +# in the network-script field. +# +# This script creates a bridge (default ${netdev}), adds a device +# (defaults to the device on the default gateway route) to it, copies +# the IP addresses from the device to the bridge and adjusts the routes +# accordingly. +# +# If all goes well, this should ensure that networking stays up. +# However, some configurations are upset by this, especially +# NFS roots. If the bridged setup does not meet your needs, +# configure a different script, for example using routing instead. +# +# Usage: +# +# network-bridge (start|stop|status) {VAR=VAL}* +# +# Vars: +# +# bridge The bridge to use (default ${netdev}). +# netdev The interface to add to the bridge (default gateway device). +# antispoof Whether to use iptables to prevent spoofing (default no). +# +# Internal Vars: +# pdev="p${netdev}" +# tdev=tmpbridge +# +# start: +# Creates the bridge as tdev +# Copies the IP and MAC addresses from pdev to bridge +# Renames netdev to be pdev +# Renames tdev to bridge +# Enslaves pdev to bridge +# +# stop: +# Removes pdev from the bridge +# Transfers addresses, routes from bridge to pdev +# Renames bridge to tdev +# Renames pdev to netdev +# Deletes tdev +# +# status: +# Print addresses, interfaces, routes +# +#============================================================================ + + +dir=$(dirname "$0") +. "$dir/logging.sh" +. "$dir/xen-script-common.sh" +. "$dir/xen-network-common.sh" +. "$dir/locking.sh" + +findCommand "$@" +evalVariables "$@" + +is_network_root () { + local rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' /etc/mtab) + local rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab) + + [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev" ]] && has_nfsroot=1 || has_nfsroot=0 + if [ $has_nfsroot -eq 1 ]; then + local bparms=$(cat /proc/cmdline) + for p in $bparms; do + local ipaddr=$(echo $p | awk /nfsroot=/'{ print substr($1,9,index($1,":")-9) }') + if [ "$ipaddr" != "" ]; then + local nfsdev=$(ip route get $ipaddr | awk /$ipaddr/'{ print $3 }') + [[ "$nfsdev" == "$netdev" ]] && return 0 || return 1 + fi + done + fi + return 1 +} + +find_alt_device () { + local interf=$1 + local prefix=${interf%[[:digit:]]} + local ifs=$(ip link show | grep " $prefix" |\ + awk '{ printf ("%s",substr($2,1,length($2)-1)) }' |\ + sed s/$interf//) + echo "$ifs" +} + +netdev=${netdev:-$(ip route list 0.0.0.0/0 | \ + sed 's/.*dev \([a-z]\+[0-9]\+\).*$/\1/')} +if is_network_root ; then + altdevs=$(find_alt_device $netdev) + for netdev in $altdevs; do break; done + if [ -z "$netdev" ]; then + [ -x /usr/bin/logger ] && /usr/bin/logger "network-bridge: bridging not supported on network root; not starting" + exit + fi +fi +netdev=${netdev:-eth0} +bridge=${bridge:-${netdev}} +antispoof=${antispoof:-no} + +pdev="p${netdev}" +tdev=tmpbridge + +get_ip_info() { + addr_pfx=`ip addr show dev $1 | egrep '^ *inet' | sed -e 's/ *inet //' -e 's/ .*//'` + gateway=`ip route show dev $1 | fgrep default | sed 's/default via //'` +} + +do_ifup() { + if [ $1 != "${netdev}" ] || ! ifup $1 ; then + if [ -n "$addr_pfx" ] ; then + # use the info from get_ip_info() + ip addr flush $1 + ip addr add ${addr_pfx} dev $1 + fi + ip link set dev $1 up + [ -n "$gateway" ] && ip route add default via ${gateway} + fi +} + +# Usage: transfer_addrs src dst +# Copy all IP addresses (including aliases) from device $src to device $dst. +transfer_addrs () { + local src=$1 + local dst=$2 + # Don't bother if $dst already has IP addresses. + if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then + return + fi + # Address lines start with 'inet' and have the device in them. + # Replace 'inet' with 'ip addr add' and change the device name $src + # to 'dev $src'. + ip addr show dev ${src} | egrep '^ *inet ' | sed -e " +s/inet/ip addr add/ +s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@ +s/${src}/dev ${dst} label ${dst}/ +s/secondary// +" | sh -e + # Remove automatic routes on destination device + ip route list | sed -ne " +/dev ${dst}\( \|$\)/ { + s/^/ip route del / + p +}" | sh -e +} + +# Usage: transfer_routes src dst +# Get all IP routes to device $src, delete them, and +# add the same routes to device $dst. +# The original routes have to be deleted, otherwise adding them +# for $dst fails (duplicate routes). +transfer_routes () { + local src=$1 + local dst=$2 + # List all routes and grep the ones with $src in. + # Stick 'ip route del' on the front to delete. + # Change $src to $dst and use 'ip route add' to add. + ip route list | sed -ne " +/dev ${src}\( \|$\)/ { + h + s/^/ip route del / + P + g + s/${src}/${dst}/ + s/^/ip route add / + P + d +}" | sh -e +} + + +## +# link_exists interface +# +# Returns 0 if the interface named exists (whether up or down), 1 otherwise. +# +link_exists() +{ + if ip link show "$1" >/dev/null 2>/dev/null + then + return 0 + else + return 1 + fi +} + +# Set the default forwarding policy for $dev to drop. +# Allow forwarding to the bridge. +antispoofing () { + iptables -P FORWARD DROP + iptables -F FORWARD + iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT +} + +# Usage: show_status dev bridge +# Print ifconfig and routes. +show_status () { + local dev=$1 + local bridge=$2 + + echo '============================================================' + ip addr show ${dev} + ip addr show ${bridge} + echo ' ' + brctl show ${bridge} + echo ' ' + ip route list + echo ' ' + route -n + echo '============================================================' +} + +op_start () { + if [ "${bridge}" = "null" ] ; then + return + fi + + if [ `brctl show | wc -l` != 1 ]; then + return + fi + + if link_exists "$pdev"; then + # The device is already up. + return + fi + + claim_lock "network-bridge" + + create_bridge ${tdev} + + preiftransfer ${netdev} + transfer_addrs ${netdev} ${tdev} + # Remember slaves for bonding interface. + if [ -e /sys/class/net/${netdev}/bonding/slaves ]; then + slaves=`cat /sys/class/net/${netdev}/bonding/slaves` + fi + # Remember the IP details for do_ifup. + get_ip_info ${netdev} + if ! ifdown ${netdev}; then + ip link set ${netdev} down + ip addr flush ${netdev} + fi + ip link set ${netdev} name ${pdev} + ip link set ${tdev} name ${bridge} + + setup_physical_bridge_port ${pdev} + + # Restore slaves + if [ -n "${slaves}" ]; then + ip link set ${pdev} up + ifenslave ${pdev} ${slaves} + fi + add_to_bridge2 ${bridge} ${pdev} + do_ifup ${bridge} + + if [ ${antispoof} = 'yes' ] ; then + antispoofing + fi + + release_lock "network-bridge" +} + +op_stop () { + if [ "${bridge}" = "null" ]; then + return + fi + if ! link_exists "$bridge"; then + return + fi + if ! [ -e "/sys/class/net/${bridge}/brif/${pdev}" ]; then + # $bridge is not a bridge to which pdev is enslaved + return + fi + + claim_lock "network-bridge" + + transfer_addrs ${bridge} ${pdev} + if ! ifdown ${bridge}; then + get_ip_info ${bridge} + fi + ip link set ${pdev} down + ip addr flush ${bridge} + + brctl delif ${bridge} ${pdev} + ip link set ${bridge} down + + ip link set ${bridge} name ${tdev} + ip link set ${pdev} name ${netdev} + do_ifup ${netdev} + + brctl delbr ${tdev} + + release_lock "network-bridge" +} + +# adds $dev to $bridge but waits for $dev to be in running state first +add_to_bridge2() { + local bridge=$1 + local dev=$2 + local maxtries=10 + + echo -n "Waiting for ${dev} to negotiate link." + ip link set ${dev} up + for i in `seq ${maxtries}` ; do + if ifconfig ${dev} | grep -q RUNNING ; then + break + else + echo -n '.' + sleep 1 + fi + done + + if [ ${i} -eq ${maxtries} ] ; then echo -n '(link isnt in running state)' ; fi + echo + + add_to_bridge ${bridge} ${dev} +} + +case "$command" in + start) + op_start + ;; + + stop) + op_stop + ;; + + status) + show_status ${netdev} ${bridge} + ;; + + *) + echo "Unknown command: $command" >&2 + echo 'Valid commands are: start, stop, status' >&2 + exit 1 +esac diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/network-nat b/scripts_debian/extra-qubes-files/etc/xen/scripts/network-nat new file mode 100755 index 0000000..eb1740e --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/network-nat @@ -0,0 +1,124 @@ +#!/bin/bash +#============================================================================ +# Default Xen network start/stop script when using NAT. +# Xend calls a network script when it starts. +# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp +# in the network-script field. +# +# Usage: +# +# network-nat (start|stop|status) {VAR=VAL}* +# +# Vars: +# +# netdev The gateway interface (default eth0). +# antispoof Whether to use iptables to prevent spoofing (default no). +# dhcp Whether to alter the local DHCP configuration (default no). +# +#============================================================================ + +dir=$(dirname "$0") +. "$dir/hotplugpath.sh" +. "$dir/xen-script-common.sh" +. "$dir/xen-network-common.sh" + +findCommand "$@" +evalVariables "$@" + +netdev=${netdev:-eth0} +# antispoofing not yet implemented +antispoof=${antispoof:-no} + +# turn on dhcp feature by default if dhcpd is installed +if [ -f /etc/dhcpd.conf ] +then + dhcp=${dhcp:-yes} +else + dhcp=${dhcp:-no} +fi + + +if [ "$dhcp" != 'no' ] +then + dhcpd_conf_file=$(find_dhcpd_conf_file) + dhcpd_init_file=$(find_dhcpd_init_file) + if [ -z "$dhcpd_conf_file" ] || [ -z "$dhcpd_init_file" ] + then + echo 'Failed to find dhcpd configuration or init file.' >&2 + exit 1 + fi +fi + +domain_name=`cat /etc/resolv.conf | grep -v "#" | grep -E 'search|domain' -i | tail -n 1 | awk '{ print $2 }'` +nameserver=`cat /etc/resolv.conf | grep -v "#" | grep "nameserver" -i -m 1 | awk '{ print $2 }'` + +function dhcp_start() +{ + if ! grep -q "subnet 10.0.0.0" "$dhcpd_conf_file" + then + echo >>"$dhcpd_conf_file" "subnet 10.0.0.0 netmask 255.255.0.0 {\ + option domain-name \"$domain_name\";\ + option domain-name-servers $nameserver; }" + fi + + "$dhcpd_init_file" restart +} + + +function dhcp_stop() +{ + local tmpfile=$(mktemp) + grep -v "subnet 10.0.0.0" "$dhcpd_conf_file" >"$tmpfile" + if diff "$tmpfile" "$dhcpd_conf_file" >&/dev/null + then + rm "$tmpfile" + else + mv "$tmpfile" "$dhcpd_conf_file" + fi + + "$dhcpd_init_file" restart +} + + +op_start() { + echo 1 >/proc/sys/net/ipv4/ip_forward + iptables -t nat -A POSTROUTING -o ${netdev} -j MASQUERADE + [ "$dhcp" != 'no' ] && dhcp_start +} + + +op_stop() { + [ "$dhcp" != 'no' ] && dhcp_stop + iptables -t nat -D POSTROUTING -o ${netdev} -j MASQUERADE +} + + +show_status() { + echo '============================================================' + ifconfig + echo ' ' + ip route list + echo ' ' + route -n + echo '============================================================' + +} + +case "$command" in + start) + op_start + ;; + + stop) + op_stop + ;; + + status) + show_status + ;; + + *) + echo "Unknown command: $command" >&2 + echo 'Valid commands are: start, stop, status' >&2 + exit 1 +esac diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/network-route b/scripts_debian/extra-qubes-files/etc/xen/scripts/network-route new file mode 100755 index 0000000..8f6a1be --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/network-route @@ -0,0 +1,28 @@ +#!/bin/bash +#============================================================================ +# Default Xen network start/stop script. +# Xend calls a network script when it starts. +# The script name to use is defined in ${XEN_CONFIG_DIR}/xend-config.sxp +# in the network-script field. +# +# Usage: +# +# network-route (start|stop|status) {VAR=VAL}* +# +# Vars: +# +# netdev The gateway interface (default eth0). +# antispoof Whether to use iptables to prevent spoofing (default yes). +# +#============================================================================ + +dir=$(dirname "$0") +. "$dir/hotplugpath.sh" +. "$dir/xen-script-common.sh" + +evalVariables "$@" + +netdev=${netdev:-eth0} + +echo 1 >/proc/sys/net/ipv4/ip_forward +echo 1 >/proc/sys/net/ipv4/conf/${netdev}/proxy_arp diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-bridge b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-bridge new file mode 100755 index 0000000..960784a --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-bridge @@ -0,0 +1,108 @@ +#!/bin/bash +#============================================================================ +# ${XEN_SCRIPT_DIR}/vif-bridge +# +# Script for configuring a vif in bridged mode. +# The hotplugging system will call this script if it is specified either in +# the device configuration given to Xend, or the default Xend configuration +# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in +# neither of those places, then this script is the default. +# +# Usage: +# vif-bridge (add|remove|online|offline) +# +# Environment vars: +# vif vif interface name (required). +# XENBUS_PATH path to this device's details in the XenStore (required). +# +# Read from the store: +# bridge bridge to add the vif to (optional). Defaults to searching for the +# bridge itself. +# ip list of IP networks for the vif, space-separated (optional). +# +# up: +# Enslaves the vif interface to the bridge and adds iptables rules +# for its ip addresses (if any). +# +# down: +# Removes the vif interface from the bridge and removes the iptables +# rules for its ip addresses (if any). +#============================================================================ + +dir=$(dirname "$0") +. "$dir/vif-common.sh" + +bridge=${bridge:-} +bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge") + +if [ -z "$bridge" ] +then + bridge=$(brctl show | cut -d " +" -f 2 | cut -f 1) + + if [ -z "$bridge" ] + then + fatal "Could not find bridge, and none was specified" + fi +else + # + # Old style bridge setup with netloop, used to have a bridge name + # of xenbrX, enslaving pethX and vif0.X, and then configuring + # eth0. + # + # New style bridge setup does not use netloop, so the bridge name + # is ethX and the physical device is enslaved pethX + # + # So if... + # + # - User asks for xenbrX + # - AND xenbrX doesn't exist + # - AND there is a ethX device which is a bridge + # + # ..then we translate xenbrX to ethX + # + # This lets old config files work without modification + # + if [ ! -e "/sys/class/net/$bridge" ] && [ -z "${bridge##xenbr*}" ] + then + if [ -e "/sys/class/net/eth${bridge#xenbr}/bridge" ] + then + bridge="eth${bridge#xenbr}" + fi + fi +fi + +RET=0 +ip link show $bridge 1>/dev/null 2>&1 || RET=1 +if [ "$RET" -eq 1 ] +then + fatal "Could not find bridge device $bridge" +fi + +case "$command" in + online) + setup_virtual_bridge_port "$dev" + mtu="`ip link show $bridge | awk '/mtu/ { print $5 }'`" + if [ -n "$mtu" ] && [ "$mtu" -gt 0 ] + then + ip link set $dev mtu $mtu || : + fi + add_to_bridge "$bridge" "$dev" + ;; + + offline) + do_without_error brctl delif "$bridge" "$dev" + do_without_error ifconfig "$dev" down + ;; + + add) + setup_virtual_bridge_port "$dev" + add_to_bridge "$bridge" "$dev" + ;; +esac + +log debug "Successful vif-bridge $command for $dev, bridge $bridge." +if [ "$type_if" = vif -a "$command" = "online" ] +then + success +fi diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-common.sh new file mode 100755 index 0000000..c9c5d41 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-common.sh @@ -0,0 +1,190 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" +. "$dir/xen-network-common.sh" + +findCommand "$@" + +if [ "$command" != "online" ] && + [ "$command" != "offline" ] && + [ "$command" != "add" ] && + [ "$command" != "remove" ] +then + log err "Invalid command: $command" + exit 1 +fi + + +# Parameters may be read from the environment, the command line arguments, and +# the store, with overriding in that order. The environment is given by the +# driver, the command line is given by the Xend global configuration, and +# store details are given by the per-domain or per-device configuration. + +evalVariables "$@" + +# Older versions of Xen do not pass in the type as an argument, +# so the default value is vif. +: ${type_if:=vif} + +case "$type_if" in + vif) + dev=$vif + ;; + tap) + dev=$INTERFACE + ;; + *) + log err "unknown interface type $type_if" + exit 1 + ;; +esac + +case "$command" in + online | offline) + test "$type_if" != vif && exit 0 + ;; + add | remove) + test "$type_if" != tap && exit 0 + ;; +esac + + +if [ "$type_if" = vif ]; then + # Check presence of compulsory args. + XENBUS_PATH="${XENBUS_PATH:?}" + dev="${dev:?}" + + vifname=$(xenstore_read_default "$XENBUS_PATH/vifname" "") + if [ "$vifname" ] + then + if [ "$command" == "online" ] && ! ip link show "$vifname" >&/dev/null + then + do_or_die ip link set "$dev" name "$vifname" + fi + dev="$vifname" + fi +elif [ "$type_if" = tap ]; then + # Check presence of compulsory args. + : ${INTERFACE:?} + + # Get xenbus_path from device name. + # The name is built like that: "tap${domid}.${devid}". + dev_=${dev#tap} + domid=${dev_%.*} + devid=${dev_#*.} + + XENBUS_PATH="/local/domain/0/backend/vif/$domid/$devid" +fi + +ip=${ip:-} +ip=$(xenstore_read_default "$XENBUS_PATH/ip" "$ip") + +frob_iptable() +{ + if [ "$command" == "online" ] + then + local c="-I" + else + local c="-D" + fi + + iptables "$c" FORWARD -m physdev --physdev-is-bridged --physdev-in "$dev" \ + "$@" -j ACCEPT 2>/dev/null && + iptables "$c" FORWARD -m physdev --physdev-is-bridged --physdev-out "$dev" \ + -j ACCEPT 2>/dev/null + + if [ "$command" == "online" -a $? -ne 0 ] + then + log err "iptables setup failed. This may affect guest networking." + fi +} + + +## +# Add or remove the appropriate entries in the iptables. With antispoofing +# turned on, we have to explicitly allow packets to the interface, regardless +# of the ip setting. If ip is set, then we additionally restrict the packets +# to those coming from the specified networks, though we allow DHCP requests +# as well. +# +handle_iptable() +{ + # Check for a working iptables installation. Checking for the iptables + # binary is not sufficient, because the user may not have the appropriate + # modules installed. If iptables is not working, then there's no need to do + # anything with it, so we can just return. + if ! iptables -L -n >&/dev/null + then + return + fi + + claim_lock "iptables" + + if [ "$ip" != "" ] + then + local addr + for addr in $ip + do + frob_iptable -s "$addr" + done + + # Always allow the domain to talk to a DHCP server. + frob_iptable -p udp --sport 68 --dport 67 + else + # No IP addresses have been specified, so allow anything. + frob_iptable + fi + + release_lock "iptables" +} + + +## +# ip_of interface +# +# Print the IP address currently in use at the given interface, or nothing if +# the interface is not up. +# +ip_of() +{ + ip addr show "$1" | awk "/^.*inet.*$1\$/{print \$2}" | sed -n '1 s,/.*,,p' +} + + +## +# dom0_ip +# +# Print the IP address of the interface in dom0 through which we are routing. +# This is the IP address on the interface specified as "netdev" as a parameter +# to these scripts, or eth0 by default. This function will call fatal if no +# such interface could be found. +# +dom0_ip() +{ + local nd=${netdev:-eth0} + local result=$(ip_of "$nd") + if [ -z "$result" ] + then + fatal +"$netdev is not up. Bring it up or specify another interface with " \ +"netdev= as a parameter to $0." + fi + echo "$result" +} diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-nat b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-nat new file mode 100755 index 0000000..9082cc9 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-nat @@ -0,0 +1,192 @@ +#!/bin/bash +#============================================================================ +# ${XEN_SCRIPT_DIR}/vif-nat +# +# Script for configuring a vif in routed-nat mode. +# The hotplugging system will call this script if it is specified either in +# the device configuration given to Xend, or the default Xend configuration +# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in +# neither of those places, then vif-bridge is the default. +# +# Usage: +# vif-nat (add|remove|online|offline) +# +# Environment vars: +# dev vif interface name (required). +# XENBUS_PATH path to this device's details in the XenStore (required). +# +# Parameters: +# dhcp Whether to alter the local DHCP configuration to include this +# new host (default no). +# +# Read from the store: +# ip list of IP networks for the vif, space-separated (default given in +# this script). +#============================================================================ + + +dir=$(dirname "$0") +. "$dir/vif-common.sh" + +# turn on dhcp feature by default if dhcpd is installed +if [ -f /etc/dhcpd.conf ] +then + dhcp=${dhcp:-yes} +else + dhcp=${dhcp:-no} +fi + +if [ "$dhcp" != 'no' ] +then + dhcpd_conf_file=$(find_dhcpd_conf_file) + dhcpd_init_file=$(find_dhcpd_init_file) + dhcpd_arg_file=$(find_dhcpd_arg_file) + if [ -z "$dhcpd_conf_file" ] || [ -z "$dhcpd_init_file" ] || [ -z "$dhcpd_arg_file" ] + then + echo 'Failed to find dhcpd configuration or init or args file.' >&2 + exit 1 + fi +fi + + +domid=$(xenstore_read "$XENBUS_PATH/frontend-id") +vifid=$(xenstore_read "$XENBUS_PATH/handle") +vifid=$(( $vifid + 1 )) + + +ip_from_dom() +{ + local domid1=$(( $domid / 256 )) + local domid2=$(( $domid % 256 )) + + echo "10.$domid1.$domid2.$vifid/16" +} + + +routing_ip() +{ + echo $(echo $1 | awk -F. '{print $1"."$2"."$3"."$4 + 127}') +} + + +dotted_quad() +{ + echo\ + $(( ($1 & 0xFF000000) >> 24))\ +.$(( ($1 & 0x00FF0000) >> 16))\ +.$(( ($1 & 0x0000FF00) >> 8 ))\ +.$(( $1 & 0x000000FF )) +} + + +if [ "$ip" = "" ] +then + ip=$(ip_from_dom) +fi + +router_ip=$(routing_ip "$ip") + +# Split the given IP/bits pair. +vif_ip=`echo ${ip} | awk -F/ '{print $1}'` + +hostname=$(xenstore_read "$XENBUS_PATH/domain" | tr -- '_.:/+' '-----') +if [ "$vifid" != "1" ] +then + hostname="$hostname-$vifid" +fi + +dhcparg_remove_entry() +{ + local tmpfile=$(mktemp) + sed -e "s/${dev} //" "$dhcpd_arg_file" >"$tmpfile" + if diff "$tmpfile" "$dhcpd_arg_file" >/dev/null + then + rm "$tmpfile" + else + mv "$tmpfile" "$dhcpd_arg_file" + fi +} + +dhcparg_add_entry() +{ + dhcparg_remove_entry + local tmpfile=$(mktemp) + # handle Red Hat, SUSE, and Debian styles, with or without quotes + sed -e 's/^DHCPDARGS="*\([^"]*\)"*/DHCPDARGS="\1'"${dev} "'"/' \ + "$dhcpd_arg_file" >"$tmpfile" && mv "$tmpfile" "$dhcpd_arg_file" + sed -e 's/^DHCPD_INTERFACE="*\([^"]*\)"*/DHCPD_INTERFACE="\1'"${dev} "'"/' \ + "$dhcpd_arg_file" >"$tmpfile" && mv "$tmpfile" "$dhcpd_arg_file" + sed -e 's/^INTERFACES="*\([^"]*\)"*/INTERFACES="\1'"${dev} "'"/' \ + "$dhcpd_arg_file" >"$tmpfile" && mv "$tmpfile" "$dhcpd_arg_file" + rm -f "$tmpfile" +} + +dhcp_remove_entry() +{ + local tmpfile=$(mktemp) + grep -v "host $hostname" "$dhcpd_conf_file" >"$tmpfile" + if diff "$tmpfile" "$dhcpd_conf_file" >/dev/null + then + rm "$tmpfile" + else + mv "$tmpfile" "$dhcpd_conf_file" + fi + dhcparg_remove_entry +} + + +dhcp_up() +{ + claim_lock "vif-nat-dhcp" + dhcp_remove_entry + mac=$(xenstore_read "$XENBUS_PATH/mac") + echo >>"$dhcpd_conf_file" \ +"host $hostname { hardware ethernet $mac; fixed-address $vif_ip; option routers $router_ip; option host-name \"$hostname\"; }" + dhcparg_add_entry + release_lock "vif-nat-dhcp" + "$dhcpd_init_file" restart || true +} + + +dhcp_down() +{ + claim_lock "vif-nat-dhcp" + dhcp_remove_entry + release_lock "vif-nat-dhcp" + "$dhcpd_init_file" restart || true # We need to ignore failure because + # ISC dhcpd 3 borks if there is nothing + # for it to do, which is the case if + # the outgoing interface is not + # configured to offer leases and there + # are no vifs. +} + + +case "$command" in + online) + if ip route | grep -q "dev ${dev}" + then + log debug "${dev} already up" + exit 0 + fi + + do_or_die ip link set "${dev}" up arp on + do_or_die ip addr add "$router_ip" dev "${dev}" + do_or_die ip route add "$vif_ip" dev "${dev}" src "$router_ip" + echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp + [ "$dhcp" != 'no' ] && dhcp_up + ;; + offline) + [ "$dhcp" != 'no' ] && dhcp_down + do_without_error ifconfig "${dev}" down + ;; +esac + + +handle_iptable + +log debug "Successful vif-nat $command for ${dev}." +if [ "$command" = "online" ] +then + success +fi diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route new file mode 100755 index 0000000..6c5587a --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route @@ -0,0 +1,56 @@ +#!/bin/bash +#============================================================================ +# ${XEN_SCRIPT_DIR}/vif-route +# +# Script for configuring a vif in routed mode. +# The hotplugging system will call this script if it is specified either in +# the device configuration given to Xend, or the default Xend configuration +# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in +# neither of those places, then vif-bridge is the default. +# +# Usage: +# vif-route (add|remove|online|offline) +# +# Environment vars: +# dev vif interface name (required). +# XENBUS_PATH path to this device's details in the XenStore (required). +# +# Read from the store: +# ip list of IP networks for the vif, space-separated (default given in +# this script). +#============================================================================ + +dir=$(dirname "$0") +. "${dir}/vif-common.sh" + +main_ip=$(dom0_ip) + +case "${command}" in + online) + ifconfig ${dev} ${main_ip} netmask 255.255.255.255 up + echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp + ipcmd='add' + cmdprefix='' + ;; + offline) + do_without_error ifdown ${dev} + ipcmd='del' + cmdprefix='do_without_error' + ;; +esac + +if [ "${ip}" ] ; then + # If we've been given a list of IP addresses, then add routes from dom0 to + # the guest using those addresses. + for addr in ${ip} ; do + ${cmdprefix} ip route ${ipcmd} ${addr} dev ${dev} src ${main_ip} + done +fi + +handle_iptable + +log debug "Successful vif-route ${command} for ${dev}." +if [ "${command}" = "online" ] +then + success +fi diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route-qubes b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route-qubes new file mode 100755 index 0000000..68fbf38 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-route-qubes @@ -0,0 +1,65 @@ +#!/bin/bash +#============================================================================ +# /etc/xen/vif-route-qubes +# +# Script for configuring a vif in routed mode. +# The hotplugging system will call this script if it is specified either in +# the device configuration given to Xend, or the default Xend configuration +# in /etc/xen/xend-config.sxp. If the script is specified in neither of those +# places, then vif-bridge is the default. +# +# Usage: +# vif-route (add|remove|online|offline) +# +# Environment vars: +# vif vif interface name (required). +# XENBUS_PATH path to this device's details in the XenStore (required). +# +# Read from the store: +# ip list of IP networks for the vif, space-separated (default given in +# this script). +#============================================================================ + +dir=$(dirname "$0") +. "$dir/vif-common.sh" + +#main_ip=$(dom0_ip) + +case "$command" in + online) + ifconfig ${vif} up + echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp + ipcmd='add' + iptables_cmd='-I PREROUTING 1' + cmdprefix='' + ;; + offline) + do_without_error ifdown ${vif} + ipcmd='del' + iptables_cmd='-D PREROUTING' + cmdprefix='do_without_error' + ;; +esac + +domid=${vif/vif/} +domid=${domid/.*/} +# metric must be possitive, but prefer later interface +# 32752 is max XID aka domid +metric=$[ 32752 - $domid ] + +if [ "${ip}" ] ; then + # If we've been given a list of IP addresses, then add routes from dom0 to + # the guest using those addresses. + for addr in ${ip} ; do + ${cmdprefix} ip route ${ipcmd} ${addr} dev ${vif} metric $metric + done + ${cmdprefix} iptables -t raw $iptables_cmd -i ${vif} \! -s ${ip} -j DROP + back_ip=`xenstore-read qubes-netvm-gateway` + ${cmdprefix} ip addr ${ipcmd} ${back_ip}/32 dev ${vif} +fi + +log debug "Successful vif-route-qubes $command for $vif." +if [ "$command" = "online" ] +then + success +fi diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-setup b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-setup new file mode 100755 index 0000000..bcc462e --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif-setup @@ -0,0 +1,9 @@ +#!/bin/bash + +if test "$script" +then + exec $script $* +else + exec /etc/xen/scripts/vif-bridge $* +fi + diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vif2 b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif2 new file mode 100755 index 0000000..2c155be --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vif2 @@ -0,0 +1,46 @@ +#!/bin/bash + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" +. "$dir/xen-network-common.sh" + +bridge=$(xenstore_read_default "$XENBUS_PATH/bridge" "$bridge") +if [ -z "$bridge" ] + then + nr_bridges=$(($(brctl show | cut -f 1 | grep -v "^$" | wc -l) - 1)) + if [ "$nr_bridges" != 1 ] + then + fatal "no bridge specified, and don't know which one to use ($nr_bridges found)" + fi + bridge=$(brctl show | cut -d " +" -f 2 | cut -f 1) +fi + +command="$1" +shift + +case "$command" in + "online") + if [ "$bridge" != "-" ] + then + setup_virtual_bridge_port "$vif" + add_to_bridge "$bridge" "$vif" + else + # Just let the normal udev rules for interfaces handle it. + true + fi + success + ;; + + "add") + success + ;; + + "remove") + ;; + + *) + echo "Unknown command: $command" + echo 'Valid commands are: add, remove, online' + exit 1 +esac diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vscsi b/scripts_debian/extra-qubes-files/etc/xen/scripts/vscsi new file mode 100755 index 0000000..5ac2614 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vscsi @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Copyright (c) 2007, FUJITSU Limited +# Based on the block scripts code. +# + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" + +findCommand "$@" + +case "$command" in + add) + success + ;; + remove) + # TODO + exit 0 + ;; +esac + +exit 0 diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm new file mode 100755 index 0000000..38a4532 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm @@ -0,0 +1,22 @@ +#!/bin/bash + +dir=$(dirname "$0") +. "$dir/vtpm-hotplug-common.sh" + +vtpm_fatal_error=0 + +case "$command" in + add) + vtpm_create_instance + ;; + remove) + vtpm_remove_instance + ;; +esac + +if [ $vtpm_fatal_error -eq 0 ]; then + log debug "Successful vTPM operation '$command'." + success +else + fatal "Error while executing vTPM operation '$command'." +fi diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-common.sh new file mode 100755 index 0000000..d0d7935 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-common.sh @@ -0,0 +1,448 @@ +# +# Copyright (c) 2005 IBM Corporation +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +dir=$(dirname "$0") +. "$dir/logging.sh" +. "$dir/locking.sh" + +VTPMDB="/var/vtpm/vtpm.db" + +#In the vtpm-impl file some commands should be defined: +# vtpm_create, vtpm_setup, vtpm_start, etc. (see below) +if [ -r "$dir/vtpm-impl.alt" ]; then + . "$dir/vtpm-impl.alt" +elif [ -r "$dir/vtpm-impl" ]; then + . "$dir/vtpm-impl" +else + function vtpm_create () { + true + } + function vtpm_setup() { + true + } + function vtpm_start() { + true + } + function vtpm_suspend() { + true + } + function vtpm_resume() { + true + } + function vtpm_delete() { + true + } + function vtpm_migrate() { + echo "Error: vTPM migration accross machines not implemented." + } + function vtpm_migrate_local() { + echo "Error: local vTPM migration not supported" + } + function vtpm_migrate_recover() { + true + } +fi + + +#Find the instance number for the vtpm given the name of the domain +# Parameters +# - vmname : the name of the vm +# Return value +# Returns '0' if instance number could not be found, otherwise +# it returns the instance number in the variable 'instance' +function vtpmdb_find_instance () { + local vmname ret instance + vmname=$1 + ret=0 + + instance=$(cat $VTPMDB | \ + awk -vvmname=$vmname \ + '{ \ + if ( 1 != index($1,"#")) { \ + if ( $1 == vmname ) { \ + print $2; \ + exit; \ + } \ + } \ + }') + if [ "$instance" != "" ]; then + ret=$instance + fi + echo "$ret" +} + + +# Check whether a particular instance number is still available +# returns "0" if it is not available, "1" otherwise. +function vtpmdb_is_free_instancenum () { + local instance instances avail i + instance=$1 + avail=1 + #Allowed instance number range: 1-255 + if [ $instance -eq 0 -o $instance -gt 255 ]; then + avail=0 + else + instances=$(cat $VTPMDB | \ + awk \ + '{ \ + if (1 != index($1,"#")) { \ + printf("%s ",$2); \ + } \ + }') + for i in $instances; do + if [ $i -eq $instance ]; then + avail=0 + break + fi + done + fi + echo "$avail" +} + + +# Get an available instance number given the database +# Returns an unused instance number +function vtpmdb_get_free_instancenum () { + local ctr instances don found + instances=$(cat $VTPMDB | \ + awk \ + '{ \ + if (1 != index($1,"#")) { \ + printf("%s ",$2); \ + } \ + }') + ctr=1 + don=0 + while [ $don -eq 0 ]; do + found=0 + for i in $instances; do + if [ $i -eq $ctr ]; then + found=1; + break; + fi + done + + if [ $found -eq 0 ]; then + don=1 + break + fi + let ctr=ctr+1 + done + echo "$ctr" +} + + +# Add a domain name and instance number to the DB file +function vtpmdb_add_instance () { + local res vmname inst + vmname=$1 + inst=$2 + + if [ ! -f $VTPMDB ]; then + echo "#Database for VM to vTPM association" > $VTPMDB + echo "#1st column: domain name" >> $VTPMDB + echo "#2nd column: TPM instance number" >> $VTPMDB + fi + res=$(vtpmdb_validate_entry $vmname $inst) + if [ $res -eq 0 ]; then + echo "$vmname $inst" >> $VTPMDB + fi +} + + +#Validate whether an entry is the same as passed to this +#function +function vtpmdb_validate_entry () { + local res rc vmname inst + rc=0 + vmname=$1 + inst=$2 + + res=$(cat $VTPMDB | \ + awk -vvmname=$vmname \ + -vinst=$inst \ + '{ \ + if ( 1 == index($1,"#")) {\ + } else \ + if ( $1 == vmname && \ + $2 == inst) { \ + printf("1"); \ + exit; \ + } else \ + if ( $1 == vmname || \ + $2 == inst) { \ + printf("2"); \ + exit; \ + } \ + }') + + if [ "$res" == "1" ]; then + rc=1 + elif [ "$res" == "2" ]; then + rc=2 + fi + echo "$rc" +} + + +#Remove an entry from the vTPM database given its domain name +#and instance number +function vtpmdb_remove_entry () { + local vmname instance VTPMDB_TMP + vmname=$1 + instance=$2 + VTPMDB_TMP="$VTPMDB".tmp + + $(cat $VTPMDB | \ + awk -vvmname=$vmname \ + '{ \ + if ( $1 != vmname ) { \ + print $0; \ + } \ + '} > $VTPMDB_TMP) + if [ -e $VTPMDB_TMP ]; then + mv -f $VTPMDB_TMP $VTPMDB + vtpm_delete $instance + else + log err "Error creating temporary file '$VTPMDB_TMP'." + fi +} + + +# Find the reason for the creation of this device: +# Returns 'resume' or 'create' +function vtpm_get_create_reason () { + local resume + resume=$(xenstore_read $XENBUS_PATH/resume) + if [ "$resume" == "True" ]; then + echo "resume" + else + echo "create" + fi +} + + +#Create a vTPM instance +# If no entry in the TPM database is found, the instance is +# created and an entry added to the database. +function vtpm_create_instance () { + local res instance domname reason uuid + uuid=$(xenstore_read "$XENBUS_PATH"/uuid) + reason=$(vtpm_get_create_reason) + + claim_lock vtpmdb + + instance="0" + + if [ "$uuid" != "" ]; then + instance=$(vtpmdb_find_instance $uuid) + fi + if [ "$instance" == "0" ]; then + domname=$(xenstore_read "$XENBUS_PATH"/domain) + instance=$(vtpmdb_find_instance $domname) + fi + + if [ "$instance" == "0" -a "$reason" != "create" ]; then + release_lock vtpmdb + return + fi + + if [ "$instance" == "0" ]; then + #Try to give the preferred instance to the domain + instance=$(xenstore_read "$XENBUS_PATH"/pref_instance) + if [ "$instance" != "" ]; then + res=$(vtpmdb_is_free_instancenum $instance) + if [ $res -eq 0 ]; then + instance=$(vtpmdb_get_free_instancenum) + fi + else + instance=$(vtpmdb_get_free_instancenum) + fi + + vtpm_create $instance + + if [ $vtpm_fatal_error -eq 0 ]; then + if [ "$uuid" != "" ]; then + vtpmdb_add_instance $uuid $instance + else + vtpmdb_add_instance $domname $instance + fi + fi + else + if [ "$reason" == "resume" ]; then + vtpm_resume $instance + else + vtpm_start $instance + fi + fi + + release_lock vtpmdb + + xenstore_write $XENBUS_PATH/instance $instance +} + + +#Remove an instance when a VM is terminating or suspending. +#Since it is assumed that the VM will appear again, the +#entry is kept in the VTPMDB file. +function vtpm_remove_instance () { + local instance reason domname uuid + #Stop script execution quietly if path does not exist (anymore) + xenstore-exists "$XENBUS_PATH"/domain + uuid=$(xenstore_read "$XENBUS_PATH"/uuid) + + claim_lock vtpmdb + + instance="0" + + if [ "$uuid" != "" ]; then + instance=$(vtpmdb_find_instance $uuid) + fi + + if [ "$instance" == "0" ]; then + domname=$(xenstore_read "$XENBUS_PATH"/domain) + instance=$(vtpmdb_find_instance $domname) + fi + + if [ "$instance" != "0" ]; then + vtpm_suspend $instance + fi + + release_lock vtpmdb +} + + +#Remove an entry in the VTPMDB file given the domain's name +#1st parameter: The name of the domain +function vtpm_delete_instance () { + local instance + + claim_lock vtpmdb + + instance=$(vtpmdb_find_instance $1) + if [ "$instance" != "0" ]; then + vtpmdb_remove_entry $1 $instance + fi + + release_lock vtpmdb +} + +# Determine whether the given address is local to this machine +# Return values: +# "-1" : the given machine name is invalid +# "0" : this is not an address of this machine +# "1" : this is an address local to this machine +function vtpm_isLocalAddress() { + local addr res + addr=$(ping $1 -c 1 | \ + awk '{ print substr($3,2,length($3)-2); exit }') + if [ "$addr" == "" ]; then + echo "-1" + return + fi + res=$(ifconfig | grep "inet addr" | \ + awk -vaddr=$addr \ + '{ \ + if ( addr == substr($2, 6)) {\ + print "1"; \ + } \ + }' \ + ) + if [ "$res" == "" ]; then + echo "0" + return + fi + echo "1" +} + +# Perform a migration step. This function differentiates between migration +# to the local host or to a remote machine. +# Parameters: +# 1st: destination host to migrate to +# 2nd: name of the domain to migrate +# 3rd: the migration step to perform +function vtpm_migration_step() { + local res=$(vtpm_isLocalAddress $1) + if [ "$res" == "0" ]; then + vtpm_migrate $1 $2 $3 + else + vtpm_migrate_local + fi +} + +# Recover from migration due to an error. This function differentiates +# between migration to the local host or to a remote machine. +# Parameters: +# 1st: destination host the migration was going to +# 2nd: name of the domain that was to be migrated +# 3rd: the last successful migration step that was done +function vtpm_recover() { + local res + res=$(vtpm_isLocalAddress $1) + if [ "$res" == "0" ]; then + vtpm_migrate_recover $1 $2 $3 + fi +} + + +#Determine the domain id given a domain's name. +#1st parameter: name of the domain +#return value: domain id or -1 if domain id could not be determined +function vtpm_domid_from_name () { + local id name ids + ids=$(xenstore-list /local/domain) + for id in $ids; do + name=$(xenstore-read /local/domain/$id/name) + if [ "$name" == "$1" ]; then + echo "$id" + return + fi + done + echo "-1" +} + +#Determine the virtual TPM's instance number using the domain ID. +#1st parm: domain ID +function vtpm_uuid_by_domid() { + echo $(xenstore-read /local/domain/0/backend/vtpm/$1/0/uuid) +} + + +# Determine the vTPM's UUID by the name of the VM +function vtpm_uuid_from_vmname() { + local domid=$(vtpm_domid_from_name $1) + if [ "$domid" != "-1" ]; then + echo $(vtpm_uuid_by_domid $domid) + return + fi + echo "" +} + +#Add a virtual TPM instance number and its associated domain name +#to the VTPMDB file and activate usage of this virtual TPM instance +#by writing the instance number into the xenstore +#1st parm: name of virtual machine +#2nd parm: instance of associated virtual TPM +function vtpm_add_and_activate() { + local domid=$(vtpm_domid_from_name $1) + local vtpm_uuid=$(vtpm_uuid_from_vmname $1) + if [ "$vtpm_uuid" != "" -a "$domid" != "-1" ]; then + vtpmdb_add_instance $vtpm_uuid $2 + xenstore-write backend/vtpm/$domid/0/instance $2 + fi +} diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-delete b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-delete new file mode 100755 index 0000000..b75b95b --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-delete @@ -0,0 +1,18 @@ +#!/bin/bash + +# This scripts must be called the following way: +# vtpm-delete +# or +# vtpm-delete --vmname + +dir=$(dirname "$0") +. "$dir/vtpm-common.sh" + +if [ "$1" == "--vmname" ]; then + vtpm_uuid=$(vtpm_uuid_from_vmname $2) + if [ "$vtpm_uuid" != "" ];then + vtpm_delete_instance $vtpm_uuid + fi +else + vtpm_delete_instance $1 +fi diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-hotplug-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-hotplug-common.sh new file mode 100755 index 0000000..9fd35e7 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-hotplug-common.sh @@ -0,0 +1,35 @@ +# +# Copyright (c) 2005 IBM Corporation +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" + +findCommand "$@" +if [ "$command" != "online" ] && + [ "$command" != "offline" ] && + [ "$command" != "add" ] && + [ "$command" != "remove" ] +then + log err "Invalid command: $command" + exit 1 +fi + + +XENBUS_PATH="${XENBUS_PATH:?}" + +. "$dir/vtpm-common.sh" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-impl b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-impl new file mode 100755 index 0000000..4f9a1fd --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-impl @@ -0,0 +1,208 @@ +#!/bin/bash +# =================================================================== +# +# Copyright (c) 2005, Intel Corp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +# OF THE POSSIBILITY OF SUCH DAMAGE. +# =================================================================== + +# | SRC | TAG | CMD SIZE | ORD |mtype|strt +TPM_CMD_OPEN=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x11\\x01\\x00\\x00\\x01\\x01\\x01 +TPM_CMD_RESM=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x11\\x01\\x00\\x00\\x01\\x01\\x02 +TPM_CMD_CLOS=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x0e\\x01\\x00\\x00\\x02 +TPM_CMD_DELE=\\x00\\x00\\x00\\x00\\x01\\xc1\\x00\\x00\\x00\\x0e\\x01\\x00\\x00\\x03 + +TPM_TYPE_PVM=\\x01 +TPM_TYPE_HVM=\\x02 + +TPM_SUCCESS=00000000 + +TX_VTPM_MANAGER=/var/vtpm/fifos/from_console.fifo +RX_VTPM_MANAGER=/var/vtpm/fifos/to_console.fifo + +VTPM_MIG=/usr/bin/vtpm_migrator + +# -------------------- Helpers for binary streams ----------- + +function str_to_hex32() { + printf "%0.8x" $1 +} + +function hex32_to_bin() { + local inst=$(str_to_hex32 $1); + + local n1=`echo $inst | sed 's/\(..\)....../\\\\x\1/'` + local n2=`echo $inst | sed 's/..\(..\)..../\\\\x\1/'` + local n3=`echo $inst | sed 's/....\(..\)../\\\\x\1/'` + local n4=`echo $inst | sed 's/......\(..\)/\\\\x\1/'` + + echo "$n1$n2$n3$n4" +} + +function vtpm_manager_cmd() { + local cmd=$1; + local inst=$2; + local inst_bin=$(hex32_to_bin $inst); + + claim_lock vtpm_mgr + + #send cmd to vtpm_manager + printf "$cmd$inst_bin" > $TX_VTPM_MANAGER + + #recv response + set +e + local resp_hex=`dd skip=10 bs=1 count=4 if=$RX_VTPM_MANAGER 2> /dev/null | xxd -ps` + set -e + + release_lock vtpm_mgr + + #return whether the command was successful + if [ $resp_hex -ne $TPM_SUCCESS ]; then + vtpm_fatal_error=1 + false + else + true + fi +} + +# Helper to get vm type to pass to vtpm_manager open/resume +function vtpm_get_type() { + local inst=$(xenstore_read $XENBUS_PATH/frontend-id) + local vm=$(xenstore_read /local/domain/$inst/vm) + if [ "$vm" != "" ]; then + local ostype=$(xenstore-read $vm/image/ostype) + if [ "$ostype" == "hvm" ]; then + echo $TPM_TYPE_HVM; + else + echo $TPM_TYPE_PVM; + fi + fi +} + +# ------------------ Command handlers ----------------- + +# Create new vtpm instance & set it up for use +function vtpm_create () { + # Creation is handled implicitly by the manager on first setup + # so just set it up for use + $(vtpm_start $1) +} + +# Setup vtpm instance for use. +function vtpm_start() { + local vmtype=$(vtpm_get_type); + $(vtpm_manager_cmd $TPM_CMD_OPEN$vmtype $1) +} + +function vtpm_resume() { + local vmtype=$(vtpm_get_type); + $(vtpm_manager_cmd $TPM_CMD_RESM$vmtype $1) +} + +# Reset the vtpm AKA clear PCRs +function vtpm_reset() { + #not used by current implemenation + true +} + +# Shutdown the vtpm while the vm is down +# This could be a suspend of shutdown +# we cannot distinquish, so save the state +# and decide on startup if we should keep is +function vtpm_suspend() { + $(vtpm_manager_cmd $TPM_CMD_CLOS $1) +} + + +function vtpm_delete() { + local inst=$1 + if $(vtpm_manager_cmd $TPM_CMD_DELE $inst); then + rm -f /var/vtpm/vtpm_dm_$1.data + true + else + vtpm_fatal_error=1 + false + fi +} + +# Perform a migration step. This function differentiates between migration +# to the local host or to a remote machine. +# Parameters: +# 1st: destination host to migrate to +# 2nd: name of the domain to migrate +# 3rd: the migration step to perform +function vtpm_migrate() { + local instance res + + instance=$(vtpmdb_find_instance $2) + if [ "$instance" == "" ]; then + log err "VTPM Migratoin failed. Unable to translation of domain name" + echo "Error: VTPM Migration failed while looking up instance number" + fi + + case "$3" in + 0) + #Incicate migration supported + echo "0" + ;; + + 1) + # Get Public Key from Destination + # Call vtpm_manager's migration part 1 + claim_lock vtpm_mgr + $VTPM_MIG $1 $2 $instance $3 + release_lock vtpm_mgr + ;; + + 2) + # Call manager's migration step 2 and send result to destination + # If successful remove from db + claim_lock vtpm_mgr + $VTPM_MIG $1 $2 $instance $3 + release_lock vtpm_mgr + ;; + + 3) + if `ps x | grep "$VTPM_MIG $1"`; then + log err "VTPM Migration failed to complete." + echo "Error: VTPM Migration failed to complete." + fi + ;; + esac + +} + + +function vtpm_migrate_recover() { + echo "Error: Recovery not supported yet" +} + +function vtpm_migrate_local() { + echo "Error: local vTPM migration not supported" +} diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-migration.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-migration.sh new file mode 100755 index 0000000..7e38ae2 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/vtpm-migration.sh @@ -0,0 +1,19 @@ +# +# Copyright (c) 2005 IBM Corporation +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +dir=$(dirname "$0") +. "$dir/vtpm-common.sh" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-cleanup b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-cleanup new file mode 100755 index 0000000..fcaa8fc --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-cleanup @@ -0,0 +1,45 @@ +#! /bin/bash + +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" + +# Claim the lock protecting ${XEN_SCRIPT_DIR}/block. This stops a race whereby +# paths in the store would disappear underneath that script as it attempted to +# read from the store checking for device sharing. +# Any other scripts that do similar things will have to have their lock +# claimed too. +# This is pretty horrible, but there's not really a nicer way of solving this. +claim_lock "block" + +# split backend/DEVCLASS/VMID/DEVID on slashes +path_array=( ${XENBUS_PATH//\// } ) +# get /vm/UUID path +vm=$(xenstore_read_default "/local/domain/${path_array[2]}/vm" "") +# construct /vm/UUID/device/DEVCLASS/DEVID +if [ "$vm" != "" ]; then + vm_dev="$vm/device/${path_array[1]}/${path_array[3]}" + + # if the vm path does not exist and the device class is 'vbd' then we may have + # a tap2 device + $(xenstore-read "$vm_dev" 2>/dev/null) || \ + { + if [ "${path_array[1]}" = "vbd" ]; then + vm_dev="$vm/device/tap2/${path_array[3]}" + fi + } +else + vm_dev= +fi + +# remove device frontend store entries +xenstore-rm -t \ + $(xenstore-read "$XENBUS_PATH/frontend" 2>/dev/null) 2>/dev/null || true + +# remove device backend store entries +xenstore-rm -t "$XENBUS_PATH" 2>/dev/null || true +xenstore-rm -t "error/$XENBUS_PATH" 2>/dev/null || true + +# remove device path from /vm/UUID +[ "$vm_dev" != "" ] && xenstore-rm -t "$vm_dev" 2>/dev/null || true + +release_lock "block" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-common.sh new file mode 100755 index 0000000..370f9ad --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-hotplug-common.sh @@ -0,0 +1,102 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + + +dir=$(dirname "$0") +. "$dir/hotplugpath.sh" +. "$dir/logging.sh" +. "$dir/xen-script-common.sh" +. "$dir/locking.sh" + +exec 2>>/var/log/xen/xen-hotplug.log + +export PATH="${BINDIR}:${SBINDIR}:${LIBEXEC}:${PRIVATE_BINDIR}:/sbin:/bin:/usr/bin:/usr/sbin:$PATH" +export LANG="POSIX" +unset $(set | grep ^LC_ | cut -d= -f1) + +fatal() { + _xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \ + "$XENBUS_PATH/hotplug-status" error + log err "$@" + exit 1 +} + +success() { + # Tell DevController that backend is "connected" + xenstore_write "$XENBUS_PATH/hotplug-status" connected +} + +do_or_die() { + "$@" || fatal "$@ failed" +} + +do_without_error() { + "$@" 2>/dev/null || log debug "$@ failed" +} + +sigerr() { + fatal "$0 failed; error detected." +} + +trap sigerr ERR + + +## +# xenstore_read + +# +# Read each of the given paths, returning each result on a separate line, or +# exit this script if any of the paths is missing. +# +xenstore_read() { + local v=$(xenstore-read "$@" || true) + [ "$v" != "" ] || fatal "xenstore-read $@ failed." + echo "$v" +} + + +## +# xenstore_read_default +# +# Read the given path, returning the value there or the given default if the +# path is not present. +# +xenstore_read_default() { + xenstore-read "$1" 2>/dev/null || echo "$2" +} + + +## +# _xenstore_write ( )+ +# +# Write each of the key/value pairs to the store. +# +_xenstore_write() { + log debug "Writing $@ to xenstore." + xenstore-write "$@" +} + +## +# xenstore_write ( )+ +# +# Write each of the key/value pairs to the store, and exit this script if any +# such writing fails. +# +xenstore_write() { + _xenstore_write "$@" || fatal "Writing $@ to xenstore failed." +} + +log debug "$@" "XENBUS_PATH=$XENBUS_PATH" diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-network-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-network-common.sh new file mode 100755 index 0000000..f88f9b6 --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-network-common.sh @@ -0,0 +1,141 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + + +# Gentoo doesn't have ifup/ifdown, so we define appropriate alternatives. + +# Other platforms just use ifup / ifdown directly. + +## +# preiftransfer +# +# @param $1 The current name for the physical device, which is also the name +# that the virtual device will take once the physical device has +# been renamed. + +if ! which ifup >/dev/null 2>/dev/null +then + preiftransfer() + { + true + } + ifup() + { + false + } + ifdown() + { + false + } +else + preiftransfer() + { + true + } +fi + + +first_file() +{ + t="$1" + shift + for file in $@ + do + if [ "$t" "$file" ] + then + echo "$file" + return + fi + done +} + +find_dhcpd_conf_file() +{ + first_file -f /etc/dhcp3/dhcpd.conf /etc/dhcpd.conf +} + + +find_dhcpd_init_file() +{ + first_file -x /etc/init.d/{dhcp3-server,dhcp,dhcpd} +} + +find_dhcpd_arg_file() +{ + first_file -f /etc/sysconfig/dhcpd /etc/defaults/dhcp /etc/default/dhcp3-server +} + +# configure interfaces which act as pure bridge ports: +_setup_bridge_port() { + local dev="$1" + local virtual="$2" + + # take interface down ... + ip link set ${dev} down + + if [ $virtual -ne 0 ] ; then + # Initialise a dummy MAC address. We choose the numerically + # largest non-broadcast address to prevent the address getting + # stolen by an Ethernet bridge for STP purposes. + # (FE:FF:FF:FF:FF:FF) + ip link set ${dev} address fe:ff:ff:ff:ff:ff || true + fi + + # ... and configure it + ip addr flush ${dev} +} + +setup_physical_bridge_port() { + _setup_bridge_port $1 0 +} +setup_virtual_bridge_port() { + _setup_bridge_port $1 1 +} + +# Usage: create_bridge bridge +create_bridge () { + local bridge=$1 + + # Don't create the bridge if it already exists. + if [ ! -e "/sys/class/net/${bridge}/bridge" ]; then + brctl addbr ${bridge} + brctl stp ${bridge} off + brctl setfd ${bridge} 0 + # Setting these to zero stops guest<->LAN traffic + # traversing the bridge from hitting the *tables + # rulesets. guest<->host traffic still gets processed + # by the host's iptables rules so this isn't a hole + sysctl -q -w "net.bridge.bridge-nf-call-arptables=0" + sysctl -q -w "net.bridge.bridge-nf-call-ip6tables=0" + sysctl -q -w "net.bridge.bridge-nf-call-iptables=0" + fi +} + +# Usage: add_to_bridge bridge dev +add_to_bridge () { + local bridge=$1 + local dev=$2 + + # Don't add $dev to $bridge if it's already on a bridge. + if [ -e "/sys/class/net/${bridge}/brif/${dev}" ]; then + ip link set ${dev} up || true + return + fi + brctl addif ${bridge} ${dev} + ip link set ${dev} up +} + diff --git a/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-script-common.sh b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-script-common.sh new file mode 100755 index 0000000..f6841ac --- /dev/null +++ b/scripts_debian/extra-qubes-files/etc/xen/scripts/xen-script-common.sh @@ -0,0 +1,44 @@ +# +# Copyright (c) 2005 XenSource Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + + +set -e + + +evalVariables() +{ + for arg in "$@" + do + if expr 'index' "$arg" '=' '>' '1' >/dev/null + then + eval "$arg" + fi + done +} + + +findCommand() +{ + for arg in "$@" + do + if ! expr 'index' "$arg" '=' >/dev/null + then + command="$arg" + return + fi + done +} diff --git a/scripts_debian/debian-archive-keyring.gpg b/scripts_debian/keys/debian-jessie-archive-keyring.gpg similarity index 100% rename from scripts_debian/debian-archive-keyring.gpg rename to scripts_debian/keys/debian-jessie-archive-keyring.gpg diff --git a/scripts_debian/keys/debian-wheezy-archive-keyring.gpg b/scripts_debian/keys/debian-wheezy-archive-keyring.gpg new file mode 100644 index 0000000000000000000000000000000000000000..6db1f3a93c12bc0225f7156a59cc5833753d5328 GIT binary patch literal 3569 zcmYk8XFMAW*M}n_R*TlANVWFXQnU6dTD3PpBr#&eh)tCsW>H(zYVB34Hl>PEHEPvt zZK7^!d-Q(a_xC=Z&X;rk=gajw*U13h1U<{#eNRLK7{w}A2(I(TR596~20#p6i03D0 zY)Z6G%p`xx{eAySl(z@6?cDw5s(@+OPajZf1IF##w+&Gl=-E)S5nmjv!wOB}(%}|h zuxRucbiBJmRN~+!R8;9D=7(GO*t?&Gb5YTKCB{%xHe%8toUm)k?)|a3<ExmaJ2QbLOKi@lj<%xAt*B+C~U< zu!)=4E>vqGH)WGiyidpGDY-%yM_FI}A5I7_f+%StY+fdIR!B6_8yr$s=9!W}f)4%Oy zQ#CFr-J#-{mBcJXYTJDJlQrN#<>eUYojma6t7{&co_T9%(t)cgh={pX|DbA_s-oI^ zBTNA?|Au(_n+J)**2It7?6%1DaCj}07`Y0hW;qXXUZhu|{6pz~V@dzuVoXbZaUgbF z9&ca7^{G<)smG$x@wN(8hWpku;!6i@4XvT0y6-eg4di5zf?2tZV?sS2}0LQxPUPkRK?2L@5{M!UH} z(MWrU0TPZvqTmp17zV=oNLWd}AiBjP=h75dLX;|w=_D`Pfo}{@L`OB_30)I!}h04=D zY1Wi`Z{(_Ljeju4)All;6TC&`pFY}Y9Ik79rLIYBeCzXNLl7`+4K`Zbybz|Z_=V#3 z#Qu3V+V8*6l|E+1Fp*=WfZ=XTK>dg}Vc^T(UUlH~W1+Q?vbaFT(k<1y^2aQ)pCi+n z!Xs=+%0y51Q>5oc`FNJEi#9~yTIQ5x5k6i$ZyQ&b1vV>wtj+GiDjJf9CU|K)s( z*Xg;_)^QgyTj(el*FCFA5*8RfBCyscJgzG4rQ+@NwDZRf2C2WGTtPfcvAwLypo>P>ik^f-fxLD1aafo{VGrphCBbO2i;|6KW2yBK#mBK~w_q4&oI-jAL$Z8;f z7^@DVy#)k-|1$KO@Rtw|>q&fYK+J$F9Uz?g1FyrbffW54cECx>;)V9S=J_rQ0*!W;5fOpA!-e5c z6bk0(DC__ead&e;+GB*#e(1kzXBkE;YPh(1Bh;xc`7SHD&)0*hPB7WjPwCDtklNk$gLlhWyWQF_1kebt^Z#8s#Bm(Z8O)W zeLE`j7wp6=GO>w?cd5f;fM2=r8zPVK~;^*EZVA*jQ(lVbH`YT2ep(m6ft zlvwRv^PS~QN1xVrX{vVpqrJVrQI|g1m^&$P@r)7jUCfZmkQtW}q>cYBHT_3pIrJ%lHxE(!4#&j%5z zhb--e<21BrT$>b?o8KSP(le2$rg1i(tN80b0#>4!4V^*R_ylkwHhJ9GfFA@Mh~2Bh zIGt^^Xc*agTbDS>v+l{{A9ehxTdGeRil)0MbFtD=oB-i}I33<`yl9fO{I2OlaFz?K zWJ_3WU*BDGM$r8-F$rV=js@`kc^v7pCU__hy;H4@>ZYyq}qN#IfM3^Do)8Uh9Oz zAQ9!4mAp3=l8t+ol0&}nbT`+~xjH(6N$1U<1R@PL2B}EfF0)nkoM!JO?F(JBcWozW z#+-601#h4*Ryh_<-XGlco} zARup^rrEvBBaZG({5|=r6yMPHheQzUVTsSdV+RiNUvO!DVd+elV?UhgNayYjmOK9A z)Y#`_^vw)hM2vL*#2uO*{2g*z4J)?c3|g&%C$yrA49Pe=6?_qxj%A5AGvzpbkX?;e*NDt1Jy4cZ8J{85+ zvR&n#k(*JL^a1CEuJKx3N8G1D4>zU?xQW7DatQp@gY-4JiR%;ld8^;4qT+_7Fu@d` zJUQ07ve!<^V0&g_(hO`BbPmL*e>VR0W;DS+K-B2zVVTd6D27#gMJu&WRq#Fw2X&vE;(oTOHr*HP)i*`1Zr{dWHh|^Qe1(T?lAyU#h z4jWdaSyQ9a^dL`l#@1VQC*jfP15C^G-3{&6JXqB;7t8JU2Ysh1Wl{LNg+;F;24h)K z*Ra(6yF&vRF`{=jt%kqRoYDyL=muXk3YYJ?v)g^3EYSFXptaU|lYUMGr-6;;ok$B& zX_9hJYh>;y;zM`@5NzhI848B4nS;tM?bFn$R{e_-ycI-6>@SuMv6Y^`NV9zRWOO8X zbB4-=v29tbKnSWw<@DksVz+(zbxricG)AFS0*_8%Fix*IgV zT?^D>_q1TwU<;n({&ldNI#@8`F?M#k{uYN^%Wg;R^gU&@qPWsJFQ>5OXn6UUuac{k z#$<#k-q1wrDG?B`kCc=8o_aYAu`82yWZXS=WWg&G2zWFv3$W_l-YV}R4A|tp9|@Hb z&YNNz$2l}rOgxq&**?{sCsS*XNwoq^1pZW8O>D|!a{ibO2j*_%c`fZdN{yIMOSU>< zk=&kR@^i`D!wW2#l3pZ+@jRhF{b!stD9J6*HS5snj!8C7Fo+d?rtEC0ruy0P?fw3m zL~YLpi7%}UQGYEN4denbUBgHHf3Mb!|9Q3kn-yzv>MM1Q@{89!c@nkg8?5<}bF~BD z(Hac}ehQsdnIt&~Pl*P6CP@v~0@?m%zxY1boIYeVl=P*1r{_@DLwnR#fz#rilYUBt zDF3i;bX-F0dFap_F?jR^duK^)%Exoh{Ssk;cB*^?;UA-b5Lv=`jcTMp;*nmSzeY0g zkPmseHITCu+j=(xKNe|f0N~i?Y1fdN$9{h*VF2#Qc~L~G??=td-*>VY6fK`Po2ZTL zD@{u%bE~i#T6n|3d#3#OnTIkfjYNB7!%V*x?&iwc6=8@@buo?|OBq3eeqZ>f{~~e{ z9bd!>RJ5w#Zl0Z>j8y27!}K2cINjRs)HyP(#y;EEepMZDv4x@QF29xcObdf{u7WCg z4`v6u{!I6VEyL!fRN5w6O4|+qHOtn7A_*JBTcj&A7O9@$Bmm*&#}|EBJfy@QTecSNy{{?;plB$t}R60IFBM&(qUfz1ZAVT{w{C-4RT)P(iO`>FA#8rv!iK zE+Y3cEL~tBfyHKpPCbK^*}Na5(SZK(Va0|J$5|&HXTPUQ4Gy88)NI~-%V60^Dv5{2 z%*g$?EIKbDsz7p(M_4vDh8c~TgWNOZ$BhK{5G Checking for any custom $2 configuration scripts for $1..." + splitPath "$1" path_parts + + if [ "$2" ]; then + script_name="${path_parts[base]}_$2${path_parts[dotext]}" + else + script_name="${path_parts[base]}${path_parts[dotext]}" + fi + + if [ -n "${TEMPLATE_FLAVOR}" ]; then + script="$SCRIPTSDIR/custom_${DIST}_${TEMPLATE_FLAVOR}/${script_name}" + else + script="$SCRIPTSDIR/custom_${DIST}/${script_name}" + fi + + if [ -f "$script" ]; then + "$script" + fi +} + + +# ------------------------------------------------------------------------------ +# Copy extra file tree to $INSTALLDIR +# ------------------------------------------------------------------------------ +copy_dirs() { + DIR="$1" + if [ -n "${TEMPLATE_FLAVOR}" ]; then + CUSTOMDIR="$SCRIPTSDIR/custom_${DIST}_${TEMPLATE_FLAVOR}/${DIR}" + else + CUSTOMDIR="$SCRIPTSDIR/custom_${DIST}/${DIR}" + fi + + if [ -d "$CUSTOMDIR" ]; then + cp -rp "$CUSTOMDIR/"* "$INSTALLDIR" + elif [ -d "$SCRIPTSDIR/${DIR}" ]; then + cp -rp "$SCRIPTSDIR/${DIR}/"* "$INSTALLDIR" + fi +} diff --git a/umount.sh b/umount.sh new file mode 100755 index 0000000..9fc7df6 --- /dev/null +++ b/umount.sh @@ -0,0 +1,60 @@ +#!/bin/bash -e + +# +# Written by Jason Mehring (nrgaway@gmail.com) +# + +# Kills any processes within the mounted location and +# unmounts any mounts active within. +# +# To keep the actual mount mounted, add a '/' to end +# +# $1: directory to umount +# +# Examples: +# To kill all processes and mounts within 'chroot-jessie' but keep +# 'chroot-jessie' mounted: +# +# ./umount.sh chroot-jessie/ +# +# To kill all processes and mounts within 'chroot-jessie' AND also +# umount 'chroot-jessie' mount: +# +# ./umount.sh chroot-jessie +# + +# $1 = full path to mount; +# $2 = if set will not umount; only kill processes in mount +umount_image() { + MOUNTDIR="$1" + + # We need absolute paths here so we don't kill everything + if ! [[ "$MOUNTDIR" = /* ]]; then + MOUNTDIR="${PWD}/${MOUNTDIR}" + fi + + echo "-> Attempting to kill any processes still running in '$MOUNTDIR' before un-mounting" + for dir in $(sudo grep "$MOUNTDIR" /proc/mounts | cut -f2 -d" " | sort -r | grep "^$MOUNTDIR") + do + sudo lsof "$dir" 2> /dev/null | \ + grep "$dir" | \ + tail -n +2 | \ + awk '{print $2}' | \ + xargs --no-run-if-empty sudo kill -9 + + echo "un-mounting $dir" + if ! [ "$2" ] && $(mountpoint -q "$dir"); then + sudo umount -n "$dir" 2> /dev/null || \ + sudo umount -n -l "$dir" 2> /dev/null || \ + echo "umount $dir unsuccessful!" + fi + done +} + +kill_processes_in_mount() { + umount_image $1 "false" || : +} + +if [ $(basename "$0") == "umount.sh" -a "$1" ]; then + umount_image "$1" +fi