diff options
Diffstat (limited to 'test/test-functions')
-rw-r--r-- | test/test-functions | 153 |
1 files changed, 133 insertions, 20 deletions
diff --git a/test/test-functions b/test/test-functions index e69420aeca..37069396b7 100644 --- a/test/test-functions +++ b/test/test-functions @@ -21,13 +21,38 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then ROOTLIBDIR=/usr/lib/systemd fi -BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln" +PATH_TO_INIT=$ROOTLIBDIR/systemd + +BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs" DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find" STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))" STATEFILE="$STATEDIR/.testdir" TESTLOG="$STATEDIR/test.log" +is_built_with_asan() { + if ! type -P objdump >/dev/null; then + ddebug "Failed to find objdump. Assuming systemd hasn't been built with ASAN." + return 1 + fi + + # Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182 + local _asan_calls=$(objdump -dC $BUILD_DIR/systemd | egrep "callq\s+[0-9a-f]+\s+<__asan" -c) + if (( $_asan_calls < 1000 )); then + return 1 + else + return 0 + fi +} + +IS_BUILT_WITH_ASAN=$(is_built_with_asan && echo yes || echo no) + +if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then + STRIP_BINARIES=no + SKIP_INITRD=yes + PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan +fi + function find_qemu_bin() { # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm. # Either way, only use this version if we aren't running in KVM, because @@ -121,7 +146,7 @@ KERNEL_APPEND="$PARAMS \ root=/dev/sda1 \ raid=noautodetect \ loglevel=2 \ -init=$ROOTLIBDIR/systemd \ +init=$PATH_TO_INIT \ console=ttyS0 \ selinux=0 \ printk.devkmsg=on \ @@ -165,7 +190,7 @@ $KERNEL_APPEND \ run_nspawn() { [[ -d /run/systemd/system ]] || return 1 - local _nspawn_cmd="$BUILD_DIR/systemd-nspawn --register=no --kill-signal=SIGKILL --directory=$TESTDIR/nspawn-root $ROOTLIBDIR/systemd $KERNEL_APPEND" + local _nspawn_cmd="$BUILD_DIR/systemd-nspawn $NSPAWN_ARGUMENTS --register=no --kill-signal=SIGKILL --directory=$TESTDIR/$1 $PATH_TO_INIT $KERNEL_APPEND" if [[ "$NSPAWN_TIMEOUT" != "infinity" ]]; then _nspawn_cmd="timeout --foreground $NSPAWN_TIMEOUT $_nspawn_cmd" fi @@ -217,6 +242,9 @@ setup_basic_environment() { strip_binaries install_depmod_files generate_module_dependencies + if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then + create_asan_wrapper + fi } setup_selinux() { @@ -293,6 +321,46 @@ EOF chmod 0755 $_valgrind_wrapper } +create_asan_wrapper() { + local _asan_wrapper=$initdir/$ROOTLIBDIR/systemd-under-asan + ddebug "Create $_asan_wrapper" + cat >$_asan_wrapper <<EOF +#!/bin/bash + +set -x + +DEFAULT_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 +DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1 +DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:halt_on_error=1" + +mount -t proc proc /proc +mount -t sysfs sysfs /sys +mount -o remount,rw / + +PATH_TO_ASAN=\$(find / -name '*libasan*' | sed 1q) +if [[ "\$PATH_TO_ASAN" ]]; then + # A lot of services (most notably dbus) won't start without preloading libasan + # See https://github.com/systemd/systemd/issues/5004 + DEFAULT_ENVIRONMENT="\$DEFAULT_ENVIRONMENT LD_PRELOAD=\$PATH_TO_ASAN" +fi +echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf + +# ASAN and syscall filters aren't compatible with each other. +find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\)/#\\1/' + +# The redirection of ASAN reports to a file prevents them from ending up in /dev/null. +# But, apparently, sometimes it doesn't work: https://github.com/google/sanitizers/issues/886. +JOURNALD_CONF_DIR=/etc/systemd/system/systemd-journald.service.d +mkdir -p "\$JOURNALD_CONF_DIR" +printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log\n" >"\$JOURNALD_CONF_DIR/env.conf" + +export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS +exec $ROOTLIBDIR/systemd "\$@" +EOF + + chmod 0755 $_asan_wrapper +} + create_strace_wrapper() { local _strace_wrapper=$initdir/$ROOTLIBDIR/systemd-under-strace ddebug "Create $_strace_wrapper" @@ -353,20 +421,24 @@ get_ldpath() { install_missing_libraries() { # install possible missing libraries - for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/*; do + for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do LD_LIBRARY_PATH=$(get_ldpath $i) inst_libs $i done } create_empty_image() { + local _size=500 + if [[ "$STRIP_BINARIES" = "no" ]]; then + _size=$((2*_size)) + fi rm -f "$TESTDIR/rootdisk.img" # Create the blank file to use as a root filesystem - dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek=400 + dd if=/dev/null of="$TESTDIR/rootdisk.img" bs=1M seek="$_size" LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img) [ -b "$LOOPDEV" ] || return 1 echo "LOOPDEV=$LOOPDEV" >> $STATEFILE sfdisk "$LOOPDEV" <<EOF -,390M +,$((_size-10))M , EOF @@ -382,10 +454,10 @@ EOF } check_result_nspawn() { - ret=1 - [[ -e $TESTDIR/nspawn-root/testok ]] && ret=0 - [[ -f $TESTDIR/nspawn-root/failed ]] && cp -a $TESTDIR/nspawn-root/failed $TESTDIR - cp -a $TESTDIR/nspawn-root/var/log/journal $TESTDIR + local ret=1 + [[ -e $TESTDIR/$1/testok ]] && ret=0 + [[ -f $TESTDIR/$1/failed ]] && cp -a $TESTDIR/$1/failed $TESTDIR + cp -a $TESTDIR/$1/var/log/journal $TESTDIR [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) @@ -395,7 +467,7 @@ check_result_nspawn() { # can be overridden in specific test check_result_qemu() { - ret=1 + local ret=1 mkdir -p $TESTDIR/root mount ${LOOPDEV}p1 $TESTDIR/root [[ -e $TESTDIR/root/testok ]] && ret=0 @@ -433,9 +505,8 @@ install_execs() { export PKG_CONFIG_PATH=$BUILD_DIR/src/core/ systemdsystemunitdir=$(pkg-config --variable=systemdsystemunitdir systemd) systemduserunitdir=$(pkg-config --variable=systemduserunitdir systemd) - egrep -ho '^Exec[^ ]*=[^ ]+' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \ - | while read i; do - i=${i##Exec*=}; i=${i##[@+\!-]}; i=${i##\!} + sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \ + | sort -u | while read i; do # some {rc,halt}.local scripts and programs are okay to not exist, the rest should inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] done @@ -519,7 +590,15 @@ install_libnss() { install_dbus() { inst $ROOTLIBDIR/system/dbus.socket - inst $ROOTLIBDIR/system/dbus.service + + # Fedora rawhide replaced dbus.service with dbus-daemon.service + if [ -f $ROOTLIBDIR/system/dbus-daemon.service ]; then + inst $ROOTLIBDIR/system/dbus-daemon.service + # Alias symlink + inst_symlink /etc/systemd/system/dbus.service + else + inst $ROOTLIBDIR/system/dbus.service + fi find \ /etc/dbus-1 /usr/share/dbus-1 -xtype f \ @@ -552,12 +631,33 @@ install_pam() { } install_keymaps() { + # The first three paths may be deprecated. + # It seems now the last two paths are used by many distributions. for i in \ /usr/lib/kbd/keymaps/include/* \ /usr/lib/kbd/keymaps/i386/include/* \ - /usr/lib/kbd/keymaps/i386/qwerty/us.*; do + /usr/lib/kbd/keymaps/i386/qwerty/us.* \ + /usr/lib/kbd/keymaps/legacy/include/* \ + /usr/lib/kbd/keymaps/legacy/i386/qwerty/us.*; do + [[ -f $i ]] || continue + inst $i + done + + # When it takes any argument, then install more keymaps. + if [[ -n $1 ]]; then + for i in \ + /usr/lib/kbd/keymaps/i386/*/* \ + /usr/lib/kbd/keymaps/legacy/i386/*/*; do [[ -f $i ]] || continue inst $i + done + fi +} + +install_zoneinfo() { + for i in /usr/share/zoneinfo/{,*/,*/*/}*; do + [[ -f $i ]] || continue + inst $i done } @@ -595,6 +695,9 @@ setup_nspawn_root() { cp -ar $initdir $TESTDIR/nspawn-root # we don't mount in the nspawn root rm -f $TESTDIR/nspawn-root/etc/fstab + if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then + cp -ar $TESTDIR/nspawn-root $TESTDIR/unprivileged-nspawn-root + fi } setup_basic_dirs() { @@ -687,7 +790,7 @@ _lvl2char() { # This enables: # dwarn "This is a warning" # echo "This is a warning" | dwarn -LOG_LEVEL=4 +LOG_LEVEL=${LOG_LEVEL:-4} dlog() { [ -z "$LOG_LEVEL" ] && return 0 @@ -1411,11 +1514,19 @@ test_run() { fi fi if [ -z "$TEST_NO_NSPAWN" ]; then - if run_nspawn; then - check_result_nspawn || return 1 + if run_nspawn "nspawn-root"; then + check_result_nspawn "nspawn-root" || return 1 else dwarn "can't run systemd-nspawn, skipping" fi + + if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then + if NSPAWN_ARGUMENTS="-U --private-network $NSPAWN_ARGUMENTS" run_nspawn "unprivileged-nspawn-root"; then + check_result_nspawn "unprivileged-nspawn-root" || return 1 + else + dwarn "can't run systemd-nspawn, skipping" + fi + fi fi return 0 } @@ -1444,7 +1555,9 @@ do_test() { case $1 in --run) echo "TEST RUN: $TEST_DESCRIPTION" - if test_run; then + test_run + ret=$? + if (( $ret == 0 )); then echo "TEST RUN: $TEST_DESCRIPTION [OK]" else echo "TEST RUN: $TEST_DESCRIPTION [FAILED]" |