tool: wrapper script for rumpkernel tools

The rumpkernel based tools are intended to be used by executing
'tool/rump'. Since it covers the most common use cases for these
tools, this script is comparatively extensive, hence giving a short
tutorial seems reasonable:

* Format a disk image with Ext2:

To format a disk image with the Ext2 file system, first prepare the
actual image by executing dd:

! dd if=/dev/zero of=/path/to/disk_image bs=1M count=128

Second, use 'tool/rump' to format the disk image:

! rump -f -F ext2fs /path/to/disk_image

Afterwards the just created file system may be populated with the
content of another directory by executing

! rump -F ext2fs -p /path/to/another_dir /path/to/disk_image

The content of the file system image can be listed by executing

! rump -F ext2fs -l /path/to/disk_image

* Create a encrypted disk image:

Creating a cryptographic disk image based on cgd(4) is done by
executing the following command:
! rump -c /path/to/disk_image

This will generate a key that may be used to decrypt the image
later on. Since this command will _only_ generate a key and NOT
initialize the disk image, it is highly advised to prepare the disk
image by using '/dev/urandom' instead of '/dev/zero' (only new blocks
that will be written to the disk image are encrypted). In addition
while generating the key a temporary configuration file will be
created. Although this file has proper permissions, it may leak the
generated key if it is created on persistent storage. To specify a more
secure directory the '-t' option should be used:

! rump -c -t /path/to/secure/directory /path/to/disk_image

Decrypting the disk image requires the key generated in the previous
step:

! rump -c -k <key> /path/to/disk_image

For now this key has to specified as command line argument. This is
an issue if the shell, which is used, is maintaing a history of
executed commands.

For completness sake let us put all examples together by creating a
encrypted Ext2 image that will contain all files of Genode's _demo_
scenario:

! dd if=/dev/urandom of=/tmp/demo.img bs=1M count=16
! $(GENODE_DIR)/tool/rump -c -t /ramfs -F ext2fs /tmp/demo.img > \
!         /ramfs/key # key is printed out to stdout
! $(GENODE_DIR)/tool/rump -c -t /ramfs -F ext2fs -k <key> \
!         -p $(BUILD_DIR)/var/run/demo /tmp/demo.img

To check if the image was populated succesfully, execute the
following:

! $(GENODE_DIR)/tool/rump -c -t /ramfs -F ext2fs -k <key> -l \
!         /tmp/demo.img
This commit is contained in:
Josef Söntgen 2014-05-09 14:23:31 +02:00 committed by Norman Feske
parent a9e95e24fe
commit aaf0454956
2 changed files with 546 additions and 0 deletions

433
tool/rump Executable file
View File

@ -0,0 +1,433 @@
#!/bin/bash
#
# \brief Manage rumpkernel tools
# \author Josef Soentgen
# \date 2014-04-29
#
#
# Needed by glibc, otherwise loading modules as libraries for the
# rumpkernel does not work
#
export LD_DYNAMIC_WEAK=1
msg() {
[ $ARG_VERBOSE -ge 0 ] && printf -- "${1}\n"
}
debug() {
[ $ARG_VERBOSE -ge 2 ] && printf -- "\t${1}\n" > /dev/stderr
}
trap_exit() {
if [ "$RUMP_SERVER" ]; then
if [ $ARG_CRYPT_DEV -ne 0 ] && [ "$ARG_CRYPT_KEY" != "" ]; then
rump_client "cgdconfig" "-u cgd0"
fi
rump_client "halt"
fi
[ -d "$RUMP_TMP" ] && rm -rf $RUMP_TMP
}
trap_abort() {
trap_exit
[ -d "$RUMP_TMP" ] && rm -rf $RUMP_TMP
}
#
# Start the rumpkernel
#
# \param libs list of libraries (modules) the rumpkernel should
# load on start-up
# \param disks list of drivespecs the rumpkernel should attach
#
rump_server() {
local libs="$1"
local disks="$2"
$DRY_RUN $RUMP_PATH/rump_server $libs $disks $RUMP_SERVER
if [ $? -ne 0 ]; then
msg "could not start rump server."
unset RUMP_SERVER
exit 1
fi
}
#
# Run a rumpkernel client
#
# \param cmd commando to execute within the rumpkernel
# \param args arguments for the commando
#
rump_client() {
local cmd="$1"
local args="$2"
debug "$RUMP_PATH/$cmd $args"
$DRY_RUN $RUMP_PATH/$cmd $args
if [ $? -ne 0 ]; then
echo "executing '$(basename $cmd) $args' failed."
# XXX kill all processes that are still haning around
# exit 1
fi
}
#
# Encrypt or decrypt device
#
# If the key parameter is not blank decrypt the device. Otherwise
# generate a new key to encrypt.
#
# \param key key to encrypt
#
do_crypt_dev() {
local key="$1"
local args=
if [ "$key" = "" ]; then
args="-g -k storedkey -o /cgd0.conf aes-cbc 256"
else
args="cgd0 $RUMP_DISK_DEV /cgd0.conf"
fi
rump_client "cgdconfig" "$args"
}
#
# Format file system
#
# \param fs file system type
# \param dev raw device
#
do_format_fs() {
local fs="$1"
local dev="$2"
local prog=
local args=
case $fs in
ffs) prog="newfs";;
ext2fs) prog="newfs_ext2fs"; args="-I";;
*) msg "unsupported fs given."; return;;
esac
args="$args $dev"
rump_client "$prog" "$args"
}
#
# List files in the file system
#
# \param mntpt mount point of file system in the rumpkernel namespace
#
do_list_fs() {
local mntpt="$1"
rump_client "ls" "-lRah $mntpt"
}
#
# Mount fs
#
# \param fs type of file system
# \param dev device to mount
# \param mntpt mount point
#
do_mount_fs() {
local fs="$1"
local dev="$2"
local mntpt="$3"
args="$dev $mntpt"
# XXX maybe check if $mntpt exists
rump_client "mkdir" "$mntpt"
rump_client "mount_$fs" "$args"
}
#
# Umount fs
#
# \param mntpt mount point
#
do_umount_fs() {
local mntpt="$1"
rump_client "umount" "$mntpt"
}
#
# Populate fs
#
# \param top_dir root directory
#
do_populate_fs() {
local top_dir="$(readlink -f $1)"
local dirs="$(find $top_dir -mindepth 1 -type d|sed 's:'$top_dir'/::g')"
local files="$(find $top_dir -type f|sed 's:'$top_dir'/::g')"
#
# First create the directories and copy the files thereafter
#
for dir in ${dirs[*]}; do
rump_client "mkdir" "-p /mnt/$dir"
done
for file in ${files[*]}; do
target_dir="$(dirname ${file})"
rump_client "cp" "${RUMP_HOST_DIR}/${file} /mnt/${target_dir}"
done
}
#
# Create cgdconfig(8) file from given key
#
# \param config_file name of the output file
# \param key key string
#
create_cgd_config() {
local config_file=$1
local key=$2
if [ "$key" != "" ]; then
$TOOL_DIR/rump_cgdconf -k $key > $config_file
else
echo > $config_file
fi
chmod 600 $config_file
}
#
# Create temporary directory
#
# If the dir parameter is not set, create a temp directory automagically.
#
# \param dir path to the directory
#
create_temp_dir() {
local dir="$1"
if [ "$dir" != "" ]; then
RUMP_TMP="$dir"
mkdir $RUMP_TMP
else
RUMP_TMP=$(mktemp -d -t genode-rump.XXXXXX 2>&1)
[ $? -ne 0 ] && { echo 'could not create temp dir'; exit 1; }
fi
}
#
# Print usage
#
print_usage() {
local help="$1"
printf "usage: $PROG_NAME [-cfhlnvH] [-d dev] [-F fs] [-k key] "
printf "[-p dir] [-t dir] <disk_image>\n"
if [ "$help" != "" ]; then
printf "\t-c use cgd(4) to en/decrypt image\n"
printf "\t-f format image (see -F)\n"
printf "\t-h print this help screen\n"
printf "\t-l list files in disk_image\n"
printf "\t-n dry run, print commands w/o executing\n"
printf "\t-v verbose mode, may be used multiple times\n"
printf "\t-d dev device which is used for formatting within "
printf "the rumpkernel\n"
printf "\t [e.g. /blk_device or /dev/rcgd0a]\n"
printf "\t-F fs specify file system [ffs, ext2fs]\n"
printf "\t-k key use given key to access cgd(4) device\n"
printf "\t-p dir populate the image with the content of "
printf "dir\n"
printf "\t-t dir temp directory for storing rump tool "
printf "files [/tmp/genode-rump.XXXXXX]\n"
fi
}
#
# Parse commandline arguments
#
parse_arguments() {
args=$(getopt cd:fhk:lnp:t:vHF: ${*})
[ $? != 0 ] && exit 1
if [ $# -lt 1 ]
then
print_usage
exit 1
fi
set -- $args
while [ $# -ge 0 ]; do
case "$1" in
-c) ARG_CRYPT_DEV=1; shift;;
-d) ARG_DISK_DEV="$2"; shift; shift;;
-f) ARG_FORMAT_DEV=1; shift;;
-F) ARG_FORMAT_FS="$2"; shift; shift;;
-h) print_usage "help"; exit 0;;
-k) ARG_CRYPT_KEY="$2"; shift; shift;;
-l) ARG_LIST_FS=1; shift;;
-n) ARG_DRY_RUN=1; shift;;
-p) ARG_POPULATE_FS="$2"; shift; shift;;
-t) ARG_TMP_DIR="$2"; shift; shift;;
-v) ARG_VERBOSE=$(($ARG_VERBOSE + 1)); shift;;
--) shift; break;;
esac
done
if [ $# -lt 1 ]; then
msg "aborting, disk image missing."
exit 1
fi
ARG_DISK_IMAGE="$1"
if [ ! -f "$ARG_DISK_IMAGE" ]; then
msg "aborting, could not open '$ARG_DISK_IMAGE'."
exit 1
fi
if [ $ARG_LIST_FS -eq 1 ] && [ $ARG_FORMAT_DEV -eq 1 ]; then
msg "aborting, -f and -l are mutually exclusive."
exit 1
fi
if [ "$ARG_CRYPT_KEY" != "" ] && [ "$ARG_DISK_DEV" = "" ]; then
ARG_DISK_DEV="/dev/cgd0a"
fi
[ "$ARG_DISK_DEV" != "" ] && RUMP_FORMAT_DISK_DEV="$ARG_DISK_DEV"
[ $ARG_DRY_RUN -eq 1 ] && DRY_RUN=echo
if [ $ARG_FORMAT_DEV -eq 1 ] && [ "$ARG_FORMAT_FS" = "" ]; then
msg "aborting, filesystem type not specified."
exit 1
fi
}
main() {
local disk_dev=
parse_arguments "$@"
create_temp_dir "$ARG_TMP_DIR"
export RUMP_SERVER="unix://$RUMP_TMP/server_socket"
#
# First we prepare the actions...
#
if [ "$ARG_FORMAT_FS" != "" ]; then
RUMP_LIBS="$RUMP_LIBS -lrumpfs_$ARG_FORMAT_FS"
# XXX
[ "$ARG_FORMAT_FS" = "ext2fs" ] && RUMP_LIBS="$RUMP_LIBS -lrumpfs_ffs"
fi
if [ $ARG_FORMAT_DEV -eq 1 ]; then
# only add the disk image as raw device if do not
# already have another device
[ "$ARG_DISK_DEV" = "" ] && disk_dev="$disk_dev -d key=$RUMP_DISK_DEV,hostpath=$ARG_DISK_IMAGE,size=host,type=chr"
else
[ "$ARG_DISK_DEV" = "" ] && disk_dev="$disk_dev -d key=$RUMP_DISK_DEV,hostpath=$ARG_DISK_IMAGE,size=host,type=blk"
fi
if [ $ARG_CRYPT_DEV -eq 1 ]; then
RUMP_LIBS="$RUMP_LIBS -lrumpkern_crypto -lrumpdev_cgd -lrumpdev_rnd"
disk_dev="-d key=$RUMP_DISK_DEV,hostpath=$ARG_DISK_IMAGE,size=host,type=blk"
cgd_config="$RUMP_TMP/cgd0.conf"
create_cgd_config "$cgd_config" "$ARG_CRYPT_KEY"
disk_dev="$disk_dev -d key=/cgd0.conf,hostpath=$cgd_config,size=host,type=reg"
fi
if [ "$ARG_POPULATE_FS" != "" ]; then
disk_dev="$disk_dev -d key=$RUMP_HOST_DIR,hostpath=$ARG_POPULATE_FS,size=host,type=dirs"
fi
#
# ... and start the rump server...
#
rump_server "$RUMP_LIBS" "$disk_dev"
#
# ... then we execute the actions.
#
if [ $ARG_CRYPT_DEV -eq 1 ]; then
do_crypt_dev "$ARG_CRYPT_KEY"
if [ "$ARG_CRYPT_KEY" = "" ]; then
$TOOL_DIR/rump_cgdconf -f "$cgd_config"
fi
fi
if [ $ARG_FORMAT_DEV -eq 1 ]; then
do_format_fs "$ARG_FORMAT_FS" "$RUMP_FORMAT_DISK_DEV"
fi
if [ "$ARG_POPULATE_FS" != "" ]; then
do_mount_fs "$ARG_FORMAT_FS" "$RUMP_FORMAT_DISK_DEV" "/mnt"
do_populate_fs "$ARG_POPULATE_FS" "/mnt"
do_umount_fs "/mnt"
fi
if [ $ARG_LIST_FS -eq 1 ]; then
do_mount_fs "$ARG_FORMAT_FS" "$RUMP_FORMAT_DISK_DEV" "/mnt"
do_list_fs "/mnt"
do_umount_fs "/mnt"
fi
exit 0
}
PROG_NAME=$(basename $0)
ARG_CRYPT_DEV=0
ARG_FORMAT_DEV=0
ARG_DRY_RUN=0
ARG_FORMAT_FS=""
ARG_LIST_FS=0
ARG_TMP_DIR=""
ARG_VERBOSE=0
DRY_RUN=""
TOOL_DIR=$(dirname $(readlink -f $0))
GENODE_DIR=$(readlink -f $TOOL_DIR/..)
RUMP_TMP=""
RUMP_DIR="/usr/local/genode-rump"
RUMP_PATH="$RUMP_DIR/bin"
RUMP_LIBS="-lrumpdev -lrumpdev_disk -lrumpvfs"
RUMP_SERVER=""
RUMP_DISK_DEV=/disk_image
RUMP_FORMAT_DISK_DEV="$RUMP_DISK_DEV"
RUMP_HOST_DIR=/host
trap "trap_abort" INT TERM
trap "trap_exit" EXIT
main "$@"
exit 0
# End of file

113
tool/rump_cgdconf Executable file
View File

@ -0,0 +1,113 @@
#!/bin/sh
#
# \brief Create cgdconfig(8) configuration file from key or extract the key
# from the specified configuration file
# \author Josef Soentgen
# \date 2014-04-29
#
#
# Note: This script is merely just a awk(1) wrapper and only generates a
# aes-cbc 256 storedkey configuration and expects the given key to
# be a proper base64 encoded key generated by cgdconfig(8).
#
#
# Print usage
#
print_usage() {
local help=$1
printf "usage: $PROG_NAME [-h] <-f file|-k key>\n"
if [ "$help" != "" ]; then
printf "\t-h show this help screen\n"
printf "\t-k key generate config file from key and print "
printf "to stdout\n"
printf "\t-f file extract key from config file and print "
printf "to stdout\n"
fi
}
#
# Parse arguments given on the commandline
#
parse_arguments() {
local args="$(getopt hf:k: ${*})"
[ $? != 0 ] && exit 1
if [ $# -lt 1 ]
then
print_usage
exit 1
fi
set -- $args
while [ $# -ge 0 ]; do
case "$1" in
-h)
print_usage "help"
exit 0;;
-k) ARG_KEY="$2"; shift; shift;;
-f) ARG_FILE="$2"; shift; shift;;
--) shift; break;;
esac
done
}
#
# Extract the key string from the configuration file
#
extract_key() {
local cgd_file="$1"
awk 'BEGIN { found=0 }
{
if (found == 1) key=key $1
if ($1 == "keygen") { found=1; key=$4 }
}
END { sub(/;$/, "", key); print key }' $cgd_file
}
#
# Generate a proper cgd(8) configuration file from the given key
#
generate_conf() {
local key="$1"
printf "$key" | awk '{ key=$0 }
END {
printf("algorithm aes-cbc;\n")
printf("iv-method encblkno1;\n")
printf("keylength 256;\n")
printf("verify_method none;\n")
printf("keygen storedkey key ")
printf("%s \\\n", substr(key, 1, 30))
printf(" %s;\n", substr(key, 31))
}'
}
main() {
parse_arguments "$@"
if [ "$ARG_FILE" != "" ]; then
extract_key "$ARG_FILE"
fi
if [ "$ARG_KEY" != "" ]; then
generate_conf "$ARG_KEY"
fi
}
PROG_NAME=$(basename $0)
ARG_FILE=
ARG_KEY=
main "$@"
exit 0
# End of file