BUILD_DIR=uclibc-buildroot/ mkdir $BUILD_DIR tar xvf stage3-x86-uclibc-2008.0.tar.bz2 -C $BUILD_DIR tar xvf gentoo-config.tar.bz2 -C $BUILD_DIR
|
||||||||||||||||
Java is a trademark of Sun Microsystems, Inc. See here for more information. |
Build Guide for Bootstrapping a Reduced Trusted Java CompartmentAndreas Niederl, Martin PirkerThis guide is a step by step description on how to (re)build a minimalistic compartment image which is able to execute Trusted Java applications. A sample demonstration for the PrivacyCA server application is included. There are 5 major phases in the build process:
1. Linux Base SystemThe intended minimalistic application compartment is a small-sized Linux-based system consisting of the uClibc system library and a minimal user environment. To build all components for this final image it is usually easier to start from a full Linux system based on uClibc instead of creating everything by crosscompiling from a common GLibc based distribution. Thus, the first step is to bootstrap a Linux system based on uClibc. The Linux system we bootstrap is Gentoo based. Any Linux distribution can be used as a starting point, but we recommend to also start from a Gentoo Linux system. 1.1. Setup of Base SystemWe start from the Gentoo provided stage3 installation archive as base of our build system onto which we apply our own customised configuration files provided in separate tarballs. The shell variable $BUILD_DIR is used for the directory where the build system will be installed.
BUILD_DIR=uclibc-buildroot/ mkdir $BUILD_DIR tar xvf stage3-x86-uclibc-2008.0.tar.bz2 -C $BUILD_DIR tar xvf gentoo-config.tar.bz2 -C $BUILD_DIR
tar xvf portage-20090120.tar.bz2 -C $BUILD_DIR/usr
cp baselayout-lite-1.0_pre1.tar.bz2 $BUILD_DIR/usr/portage/distfiles/ cp gcc-4.3.1-uclibc-patches-1.0.tar.bz2 $BUILD_DIR/usr/portage/distfiles/ tar xvf gentoo-minimal.tar.bz2 -C $BUILD_DIR/gentoo-minimal
cp icedtea-minimal.tar.bz2 $BUILD_DIR/usr/portage/distfiles/ cp openjdk-b29.zip $BUILD_DIR/usr/portage/distfiles/
cd $BUILD_DIR/ cp /etc/resolv.conf etc/ mount -t proc none proc/ chroot . /bin/bash 1.2. Runtime Environment Support for Java
USE="-gcj" emerge -av =gcc-4.1.2 binutils && emerge -v uclibc
emerge --unmerge mktemp && emerge --oneshot coreutils
emerge --ask --verbose --update --deep --newuse world
dispatch-conf Remember: emerge prints out individual messages for certain packages containing necessary information on manual steps involved in an upgrade. Read and follow them if necessary. (Warning: Do not delete the setup_icedtea shell function in /etc/skel/.bashrc on the dispatch-conf run.)
gcc-config i686-pc-linux-uclibc-4.3.1 source /etc/profile emerge gcj-jdk java-config --set-system-vm=gcj-jdk Having prepared a usable basic build environment, the next step is installing the high-level dependencies required by IcedTea. These consist of the Ant build system, the Xalan XSLT processor, and the Xerces XML parser library. For our custom scripts we will additionally need the Z shell later on. emerge ant-eclipse-ecj xalan xalan-serializer xerces zsh 2. IcedTea Java Development Tools2.1. Prepare environment and sources
BUILD_USER="minijava" useradd --create-home --user-group $BUILD_USER
tar xvf /usr/portage/distfiles/icedtea-minimal.tar.bz2 -C /home/$BUILD_USER/ cp /usr/portage/distfiles/openjdk-b29.zip /home/$BUILD_USER/icedtea-minimal/
chown -R $BUILD_USER:$BUILD_USER /home/$BUILD_USER/
ln -s \ /home/$BUILD_USER/icedtea-minimal/openjdk-ecj/build/linux-i586/ \ /opt/icedtea The IcedTea build process exhibits random problems when run on a symmetric multiprocessing machine, e.g. computers with a multi-core cpu. However, it can be build on such computers by the use of the cpuset mechanism of the Linux kernel. The appendix contains a short guide to set up a cpuset with a single cpu in it and using it to build IcedTea. 2.2. Building IcedTea
su - $BUILD_USER cd icedtea-minimal/ unset JAVA_HOME ./configure \ --with-parallel-jobs=1 \ --with-gcj-home=$(java-config --jdk-home) \ --with-libgcj-jar=$(java-config --runtime) \ --with-ecj=/usr/bin/ecj \ --with-ecj-jar=$(java-config -p eclipse-$(eselect ecj show)) \ --with-openjdk-src-zip=./openjdk-b29.zip \ --disable-docs \ --disable-gcjwebplugin \ --disable-zero \ --without-ant-home \ --host=i686-pc-linux-uclibc \ --build=i686-pc-linux-uclibc \ --target=i686-pc-linux-uclibc make
find openjdk/build/linux-i586/j2re-image \ -type f -executable -exec strip \{\} \; find openjdk/build/linux-i586/j2sdk-image \ -type f -executable -exec strip \{\} \;
exit mv /opt/icedtea /opt/icedtea.build ln -s /home/$BUILD_USER/icedtea-minimal/openjdk/build/linux-i586/j2re-image \ /opt/icedtea
setup_icedtea() { local jhome="/opt/icedtea" [[ -n "${1}" ]] && jhome="${1}" export JAVA_HOME="${jhome}" export PATH="${JAVA_HOME}/bin:${PATH}" if [[ -d "${JAVA_HOME}"/jre ]] ; then export PATH="${JAVA_HOME}/jre/bin:${PATH}" fi export JRE_BASE_DIR="${JAVA_HOME}" } 3. Self-contained minimalistic operating environmentThe final minimal image is based on Gentoo as well. The required compartment components are copied or cross-compiled from the chroot environment built in the previous sections. We assume a plain hard disk image with a size of 50Mb as target. (Depending on later use in e.g. virtual machine setups one might have to partition it using fdisk or cfdisk and mount it differently). The path /images is used in this example, but this can be set differently.
IMAGE_DIR=/images mkdir $IMAGE_DIR dd if=/dev/zero of=$IMAGE_DIR/minimal.iso bs=1M count=50 mke2fs -F $IMAGE_DIR/minimal.iso mkdir -p /mnt/loop mount -o loop $IMAGE_DIR/minimal.iso /mnt/loop Portage is able to use a directory different from the / root directory of the system as installation base path. It can also use a different root directory to read its configuration files from. This enables keeping different package configuration completely separated. Thus, it is possible to separate the base system from the evolving system, which is created by installing packages into it. The provided xmerge wrapper script makes extensive use of this feature. In order to use it, it is necessary to set the $SYSROOT and $ROOT environment variables to the path containing our configuration files (source) and the mount point of the image respectively (destination). It is now possible to build and install all packages required for running a minimal IcedTea-based runtime environment into the image. gcc-config i686-pc-linux-uclibc-4.1.2 source /etc/profile export SYSROOT=/gentoo-minimal export ROOT=/mnt/loop xmerge -av sys-libs/uclibc sys-apps/busybox sys-apps/baselayout-lite \ sys-libs/libstdc++ sys-libs/zlib 4. Reduction and assembly of applicationsIn order to perform the Java runtime class file reduction we provide an experimental shell script which includes all the necessary stages for tailoring the Java runtime class libraries to an individual application. Dynamic profiling is used for obtaining a report of the possible minimal memory footprint. It is necessary to add the -verbose:class option on the call to the java interpreter because our script uses its classloader trace feature. Another requirement is the availability of a working jar tool program. In order to ensure the availability of a jar tool, either use the j2sdk version of IcedTea or have the system gcc set to the version used by gcj. ln -s /home/$BUILD_USER/j2sdk-image /opt/icedtea gcc-config i686-pc-linux-uclibc-4.3.1 source /etc/profile 4.1. Example: Testsuite of IAIK jTSSOur first example is the IAIK jTSS stack which implements the TCG Software Stack in the Java programming language. Fortunately, it includes a set of unit tests which can be used for automatic execution of each of its functions. setup_icedtea cd jTSS/tests export APPLICATION_BASE_DIR=$(pwd)/.. chmod 755 run_tests.sh cp run_tests.sh trace_tests.sh sed -i -e 's@java -cp@java -verbose:class -cp@' trace_tests.sh After adding the -verbose:class argument to the call to the java program in the provided run_tests.sh shell script, it can be run with our jar-strip trace script. jar-strip -u -a -n -o jTSS_env -f ./trace_tests.sh The reduced application needs additional files which are not tracked by our trace script. cp ../lib/*.ini jTSS_env/lib/app/ cp run_tests.sh jTSS_env/ It is also necessary to adapt the start script to include the new classpath. TOPDIR="${0%/*}" source "${TOPDIR}"/classpath.env exec java -cp ${CLASSPATH} iaik.tc.tss.test.tsp.java.TestMain #java -cp $CLASSPATH_LOCAL iaik.tc.tss.test.tsp.java.TestMain 4.2. Example: APKI PrivacyCA serverAnother example is the apki server component which provides an implementation of a PrivacyCA. In this scenario the individual commands are executed on the client side whereas the server side binary is being traced. Therefore, it is necessary to add the -verbose:class argument to the java program call in the server.sh shell script. In order to execute all services on the server part a test script uses all desired commands. setup_icedtea cd apki/ export APPLICATION_BASE_DIR=$(pwd) cp server.sh trace_server.sh sed -i -e 's@java -cp@java -verbose:class -cp@' trace_server.sh jar-strip -u -a -n -o apki_env -f ./trace_server.sh It is necessary to terminate the server program after calling all client commands so the wrapper script can start analysing the server dependencies. In our test setup server and client run on the same host which enables us to do this by sending a SIGKILL signal to the server with the kill command. Otherwise, this would have to be done manually. sudo -v && \ ./run_tests.sh && \ sudo kill -9 $(sudo netstat -l -p |& grep 10000 | \ awk '{print $7}' | sed -n 's:\([[:digit:]]\+\)/java$:\1:p') The script only tracks native libraries and Java archive files. Therefore, any additional file resources used by the application have to be copied into the output directory. cp -r resources certstore quotedata apki_env/ cp server.sh apki_env/ cp lib/*.ini apki_env/lib/app/ Please note that the IAIK JCE is a signed jar archive which may inhibit its functionality when modified. You should also be familiar with its license should you choose to redistribute it. Therefore, we remove this library from the minimised application which requires to add it again when the image is to be used. rm -f apki_env/lib/app/iaik_jce-3142.jar The start script must be adapted so that the classpath includes the modified archive files. It should also use exec for the execution of the program so the process ID is kept for potential later use with a daemon service init script. TOPDIR="${0%/*}" source "${TOPDIR}"/classpath.env exec java -cp ${CLASSPATH} iaik.tc.apki.APKIS $@ #java -cp ${TCCERT}:${TSP_LIB}:${JCE_LIB}:classes iaik.tc.apki.APKIS $@ Additionally, the /opt/icedtea symlink must be set to the now reduced runtime environment. In the case of the apki example this would be similar to the following commands (issued by the root user). rm -f /opt/icedtea ln -s /home/$BUILD_USER/apki/apki_env/lib/jre /opt/icedtea 4.3. Assembly of CompartmentThe final assembled compartment is a merge of the base system built in section 3.3 with the result of the Java application and runtime reduction demonstrated in section 4.1 or 4.2.
cd /mnt/loop mount -t proc none proc/ chroot . /bin/sh
USER=username adduser $USER passwd passwd $USER adduser -D -H apki HOSTNAME=example_compartment echo $HOSTNAME > /etc/hostname exit
mkdir /mnt/loop/opt cp -r apki_env /mnt/loop/opt/ APKI_USER_GROUP="$(sed -ne 's/^apki:x:\([[:digit:]]\+:[[:digit:]]\+\):.*$/\1/p' \ /mnt/loop/etc/passwd)" chown -R ${APKI_USER_GROUP} /mnt/loop/opt/apki_env ln -s /opt/apki_env/lib/jre /mnt/loop/opt/icedtea
#!/bin/sh PIDFILE="/var/run/${0##*/}" SERVERDIR="/opt/apki_env/" EXECUTABLE="${SERVERDIR}/server.sh" DAEMON_USER="apki" DAEMON_GROUP="apki" JAVA_HOME="${SERVERDIR}/lib/jre" ; export JAVA_HOME PATH="${JAVA_HOME}/bin:${PATH}" ; export PATH start() { cd "${SERVERDIR}" start-stop-daemon \ --quiet \ --background \ --make-pidfile \ --pidfile "${PIDFILE}" \ --chuid ${DAEMON_USER}:${DAEMON_GROUP} \ --exec "${EXECUTABLE}" \ --start } stop() { start-stop-daemon \ --quiet \ --pidfile "${PIDFILE}" \ --signal KILL \ --stop } [ "${1}" = "start" ] && start [ "${1}" = "stop" ] && stop
cp apki.sh /mnt/loop/etc/init.d/ cd /mnt/loop/etc/init.d ln -s apki.sh S01apki ln -s apki.sh K01apki
cd /mnt/loop mount -t proc none proc/ chroot . /bin/sh unset LANG LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE /etc/init.d/apki.sh start /etc/init.d/apki.sh stop 4.4. ComparisonThis table shows the approximate size reduction achieved in our experimental setups. The footprint of the base system can be reduced by using applications and libraries oriented towards embedded systems. However, the C++ standard library which is required by the Hotspot VM accounts for most of its size being roughly 3.5 MB large. Reducing the runtime environment to only those native libraries that are crucial for VM execution has a strong impact on its size. In this case our trace script copies only those libraries which were loaded on the reference execution of the downsized application. These libraries - including the main VM library - amount to roughly 4.1 MB in our example cases for apki and jTSS. Another major influence on the overall size of the runtime environment, additional libraries, and the target application itself are their binary class files of which we include only those which were loaded during the reference execution.
5. Software PackagesThis guide is up to date as of February 2009. The described build process is Gentoo Linux based. As Gentoo is a rolling upgrades distribution some information or packages provided here may already be out of date or incompatible to current packages and thus fixes may be necessary. The following components are used in this guide (checksums are SHA1):
If you do not want to do every step described in this document, we provide prebuilt images:
Both images of the base system include the source files of the included software in the usr/portage/distfiles directory. 6. AppendixThis section provides additional background information which may be useful for building this setup from scratch. 6.1. Sync and Upgrade of Gentoo base systemThe Portage snapshot provided is most likely out of date. You may sync and upgrade the whole system after first chrooting into it. This, however, will most likely introduce issues. You are on your own, if you choose to deviate from the packages and versions used throughout this guide!
emerge-webrsync emerge --ask --verbose --update --deep --newuse world If the used stage is unreasonably old, i.e. using an outdated toolchain (gcc/glibc) you might have to rebuild larger parts of the system set. Please read the relevant upgrade guides from http://www.gentoo.org/doc/en/, especially the Gentoo GCC Upgrade Guide. Also, the Gentoo package manager does not automatically update configuration files in order to preserve changes made by the user. Therefore, it is important to merge in changes manually if portage reports new configuration files updated by some package. 6.2. Using cpusets for limiting a chroot compartment to a single coreNewer Linux kernels support cpusets to restrict the execution of tasks and their children to specified CPUs. They use the cgroup subsystem, so make sure you have CONFIG_CGROUPS enabled in your kernel configuration. The following example assumes a quad-core CPU. Cpusets are controlled by a pseudo file system which has to be mounted first. mkdir -p /dev/cpuset mount -t cpuset -o cpuset cpuset /dev/cpuset You can create new cpusets by simply creating new directories in this file system. cd /dev/cpuset mkdir single triple It is necessary to set the memory node which is going to be used by the processes in the different sets. echo 0 > single/mems echo 0 > triple/mems In this example, we use the first three cpu cores for the triple set whereas the single set only gets to use one core. echo '0-2' > triple/cpus echo 3 > single/cpus To make use of the assignment of specific cores for a cpuset we define exclusive access for them. echo 1 > single/cpu_exclusive echo 1 > triple/cpu_exclusive Now you can start adding process ids to the different sets. Our example assigns every process currently running to the triple set. Due to short-living processes the following command can lead to error messages which can be safely ignored. for pid in $(cat /dev/cpuset/tasks) ; do echo ${pid} > triple/tasks done To have exclusive access to one core for our chroot, we add the process id of the shell being used ($$) to the single set and chroot into it. echo $$ > /dev/cpuset/single/tasks cd /my-build-dir chroot . /bin/bash [...] 7. AttributionsSun, Sun Microsystems, Java, Java runtime environment, JRE, JVM, J2RE, JDK, and OpenJDK are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both. The original efforts at IAIK to integrate TC technology into the Java programming language are part of the OpenTC project funded by the EU as part of FP-6, contract no. 027635. The project aims at providing an open source TC framework with a special focus on the Linux operating system platform. Started as an open source project the results can be inspected by everybody, thus adding towards the trustworthiness of Trusted Computing solutions. 8. ReferencesGentoo Linux IcedTea OpenJDK™ OpenTC research project Trusted Computing Group (TCG) Trusted Java |
|||||||||||||||