PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH
-LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || true)
-LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || true)
-LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || true)
+LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :)
+LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :)
+LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :)
KERNEL_VER=${KERNEL_VER-$(uname -r)}
KERNEL_MODS="/lib/modules/$KERNEL_VER/"
QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}"
EFI_MOUNT="$(bootctl -x 2>/dev/null || echo /boot)"
QEMU_MEM="${QEMU_MEM:-512M}"
+# Decide if we can (and want to) run QEMU with KVM acceleration.
+# Check if nested KVM is explicitly enabled (TEST_NESTED_KVM). If not,
+# check if it's not explicitly disabled (TEST_NO_KVM) and we're not already
+# running under KVM. If these conditions are met, enable KVM (and possibly
+# nested KVM), otherwise disable it.
+if [[ -n "$TEST_NESTED_KVM" || ( -z "$TEST_NO_KVM" && $(systemd-detect-virt -v) != kvm ) ]]; then
+ QEMU_KVM=yes
+else
+ QEMU_KVM=no
+fi
+
if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2
ROOTLIBDIR=/usr/lib/systemd
fi
PATH_TO_INIT=$ROOTLIBDIR/systemd
+[ "$SYSTEMD_JOURNALD" ] || SYSTEMD_JOURNALD=$(which -a $BUILD_DIR/systemd-journald $ROOTLIBDIR/systemd-journald 2>/dev/null | grep '^/' -m1)
+[ "$SYSTEMD" ] || SYSTEMD=$(which -a $BUILD_DIR/systemd $ROOTLIBDIR/systemd 2>/dev/null | grep '^/' -m1)
+[ "$SYSTEMD_NSPAWN" ] || SYSTEMD_NSPAWN=$(which -a $BUILD_DIR/systemd-nspawn systemd-nspawn 2>/dev/null | grep '^/' -m1)
+[ "$JOURNALCTL" ] || JOURNALCTL=$(which -a $BUILD_DIR/journalctl journalctl 2>/dev/null | grep '^/' -m1)
BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo head tail cat mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs"
DEBUGTOOLS="df free ls stty ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find vi mv"
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-journald | egrep "callq\s+[0-9a-f]+\s+<__asan" -c)
+ local _asan_calls=$(objdump -dC $SYSTEMD_JOURNALD | egrep "callq\s+[0-9a-f]+\s+<__asan" -c)
if (( $_asan_calls < 1000 )); then
return 1
else
STRIP_BINARIES=no
SKIP_INITRD="${SKIP_INITRD:-yes}"
PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan
- QEMU_MEM="1536M"
+ QEMU_MEM="2048M"
QEMU_SMP=4
# We need to correctly distinguish between gcc's and clang's ASan DSOs.
- if ldd $BUILD_DIR/systemd | grep -q libasan.so; then
+ if ldd $SYSTEMD | grep -q libasan.so; then
ASAN_COMPILER=gcc
- elif ldd $BUILD_DIR/systemd | grep -q libclang_rt.asan; then
+ elif ldd $SYSTEMD | grep -q libclang_rt.asan; then
ASAN_COMPILER=clang
# As clang's ASan DSO is usually in a non-standard path, let's check if
# We're not setting the LD_LIBRARY_PATH automagically here, because
# user should encounter (and fix) the same issue when running the unit
# tests (meson test)
- if ldd "$BUILD_DIR/systemd" | grep -q "libclang_rt.asan.*not found"; then
- _asan_rt_name="$(ldd $BUILD_DIR/systemd | awk '/libclang_rt.asan/ {print $1; exit}')"
+ if ldd "$SYSTEMD" | grep -q "libclang_rt.asan.*not found"; then
+ _asan_rt_name="$(ldd $SYSTEMD | awk '/libclang_rt.asan/ {print $1; exit}')"
_asan_rt_path="$(find /usr/lib* /usr/local/lib* -type f -name "$_asan_rt_name" 2>/dev/null | sed 1q)"
echo >&2 "clang's ASan DSO ($_asan_rt_name) is not present in the runtime library path"
echo >&2 "Consider setting LD_LIBRARY_PATH=${_asan_rt_path%/*}"
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
- # nested KVM is flaky still.
- if [[ $(systemd-detect-virt -v) != kvm && -z $TEST_NO_KVM ]] ; then
+ if [[ $QEMU_KVM == "yes" ]]; then
[ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1)
fi
[ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu 2>/dev/null | grep '^/' -m1)
;;
ppc64*)
- [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-$ARCH 2>/dev/null | grep '^/' -m1)
+ [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-ppc64 2>/dev/null | grep '^/' -m1)
;;
esac
-nographic \
-kernel $KERNEL_BIN \
-drive format=raw,cache=unsafe,file=${TESTDIR}/rootdisk.img \
+$QEMU_OPTIONS \
"
if [[ "$INITRD" && "$SKIP_INITRD" != "yes" ]]; then
QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD"
fi
- # Let's use KVM if it is available, but let's avoid using nested KVM as that is still flaky
- if [[ -c /dev/kvm && $(systemd-detect-virt -v) != kvm && -z $TEST_NO_KVM ]] ; then
+ # Let's use KVM if possible
+ if [[ -c /dev/kvm && $QEMU_KVM == "yes" ]]; then
QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host"
fi
run_nspawn() {
[[ -d /run/systemd/system ]] || return 1
- local _nspawn_cmd="$BUILD_DIR/systemd-nspawn $NSPAWN_ARGUMENTS --register=no --kill-signal=SIGKILL --directory=$TESTDIR/$1 $PATH_TO_INIT $KERNEL_APPEND"
+ local _nspawn_cmd="$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
if [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then
- dwarn "nspawn doesn't support UNIFIED_CGROUP_HIERARCHY=hybrid, skipping"
+ dwarn "nspawn doesn't support SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=hybrid, skipping"
exit
elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" || "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then
- _nspawn_cmd="env UNIFIED_CGROUP_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY $_nspawn_cmd"
+ _nspawn_cmd="env SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY $_nspawn_cmd"
elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "default" ]]; then
- _nspawn_cmd="env --unset=UNIFIED_CGROUP_HIERARCHY $_nspawn_cmd"
+ _nspawn_cmd="env --unset=UNIFIED_CGROUP_HIERARCHY --unset=SYSTEMD_NSPAWN_UNIFIED_HIERARCHY $_nspawn_cmd"
else
dfatal "Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]"
exit 1
install_dmevent() {
instmods dm_crypt =crypto
- type -P dmeventd >/dev/null && dracut_install dmeventd
- inst_libdir_file "libdevmapper-event.so*"
+ inst_binary dmeventd
if [[ "$LOOKS_LIKE_DEBIAN" ]]; then
# dmsetup installs 55-dm and 60-persistent-storage-dm on Debian/Ubuntu
# and since buster/bionic 95-dm-notify.rules
# enable debug logging in PID1
echo LogLevel=debug >> $initdir/etc/systemd/system.conf
+ # store coredumps in journal
+ echo Storage=journal >> $initdir/etc/systemd/coredump.conf
}
get_ldpath() {
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="$_size"
+ truncate -s "${_size}M" "$TESTDIR/rootdisk.img"
LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img)
[ -b "$LOOPDEV" ] || return 1
echo "LOOPDEV=$LOOPDEV" >> $STATEFILE
fi
}
+create_empty_image_rootdir() {
+ create_empty_image
+ mkdir -p $initdir
+ mount ${LOOPDEV}p1 $initdir
+ TEST_SETUP_CLEANUP_ROOTDIR=1
+}
+
check_asan_reports() {
local ret=0
local root="$1"
journald_report=$(find "$root" -name "systemd-journald.*san.log*" -exec cat {} \;)
if [[ ! -z "$journald_report" ]]; then
printf "%s\n" "$journald_report"
- cat "$root/systemd-journald.out" || true
+ cat "$root/systemd-journald.out" || :
ret=$(($ret+1))
fi
pids=$(
- "$BUILD_DIR/journalctl" -D "$root/var/log/journal" | perl -alne '
+ "$JOURNALCTL" -D "$root/var/log/journal" | perl -alne '
BEGIN {
%services_to_ignore = (
"dbus-daemon" => undef,
if [[ ! -z "$pids" ]]; then
ret=$(($ret+1))
for pid in $pids; do
- "$BUILD_DIR/journalctl" -D "$root/var/log/journal" _PID=$pid --no-pager
+ "$JOURNALCTL" -D "$root/var/log/journal" _PID=$pid --no-pager
done
fi
fi
# can be overridden in specific test
check_result_qemu() {
local ret=1
- mkdir -p $TESTDIR/root
- mount ${LOOPDEV}p1 $TESTDIR/root
- [[ -e $TESTDIR/root/testok ]] && ret=0
- [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR
- cp -a $TESTDIR/root/var/log/journal $TESTDIR
- check_asan_reports "$TESTDIR/root" || ret=$(($ret+1))
- umount $TESTDIR/root
+ mkdir -p $initdir
+ mount ${LOOPDEV}p1 $initdir
+ [[ -e $initdir/testok ]] && ret=0
+ [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
+ cp -a $initdir/var/log/journal $TESTDIR
+ check_asan_reports "$initdir" || ret=$(($ret+1))
+ umount $initdir
[[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
ls -l $TESTDIR/journal/*/*.journal
test -s $TESTDIR/failed && ret=$(($ret+1))
ddebug "Strip binaries"
find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | \
xargs strip --strip-unneeded |& \
- grep -v 'file format not recognized' | \
+ grep -vi 'file format not recognized' | \
ddebug
}
}
install_config_files() {
- inst /etc/sysconfig/init || true
+ inst /etc/sysconfig/init || :
inst /etc/passwd
inst /etc/shadow
inst /etc/login.defs
inst /etc/group
inst /etc/shells
inst /etc/nsswitch.conf
- inst /etc/pam.conf || true
- inst /etc/securetty || true
+ inst /etc/pam.conf || :
+ inst /etc/securetty || :
inst /etc/os-release
inst /etc/localtime
# we want an empty environment
ln -sfn /run/lock "$initdir/var/lock"
}
+mask_supporting_services() {
+ # mask some services that we do not want to run in these tests
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
+}
+
inst_libs() {
local _bin=$1
local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)'
import_initdir() {
initdir=$TESTDIR/root
+ mkdir -p $initdir
export initdir
}
| instmods
else
( [[ "$_mpargs" ]] && echo $_mpargs
- find "$KERNEL_MODS" -path "*/${_mod#=}/*" -printf '%f\n' ) \
+ find "$KERNEL_MODS" -path "*/${_mod#=}/*" -type f -printf '%f\n' ) \
| instmods
fi
;;
return $_ret
}
-# inst_libdir_file [-n <pattern>] <file> [<file>...]
-# Install a <file> located on a lib directory to the initramfs image
-# -n <pattern> install non-matching files
-inst_libdir_file() {
- if [[ "$1" == "-n" ]]; then
- local _pattern=$1
- shift 2
- for _dir in $libdirs; do
- for _i in "$@"; do
- for _f in "$_dir"/$_i; do
- [[ "$_i" =~ $_pattern ]] || continue
- [[ -e "$_i" ]] && dracut_install "$_i"
- done
- done
- done
- else
- for _dir in $libdirs; do
- for _i in "$@"; do
- for _f in "$_dir"/$_i; do
- [[ -e "$_f" ]] && dracut_install "$_f"
- done
- done
- done
- fi
-}
-
setup_suse() {
ln -fs ../usr/bin/systemctl $initdir/bin/
ln -fs ../usr/lib/systemd $initdir/lib/
inst_simple "/usr/lib/systemd/system/haveged.service"
}
+_umount_dir() {
+ if mountpoint -q $1; then
+ ddebug "umount $1"
+ umount $1
+ fi
+}
+
+_test_setup_cleanup() {
+ # only umount if create_empty_image_rootdir() was called to mount it
+ [[ -z $TEST_SETUP_CLEANUP_ROOTDIR ]] || _umount_dir $initdir
+}
+
+# can be overridden in specific test
+test_setup_cleanup() {
+ _test_setup_cleanup
+}
+
+_test_cleanup() {
+ # (post-test) cleanup should always ignore failure and cleanup as much as possible
+ (
+ set +e
+ _umount_dir $initdir
+ if [[ $LOOPDEV && -b $LOOPDEV ]]; then
+ ddebug "losetup -d $LOOPDEV"
+ losetup -d $LOOPDEV
+ fi
+ rm -fr "$TESTDIR"
+ rm -f "$STATEFILE"
+ ) || :
+}
+
# can be overridden in specific test
test_cleanup() {
- umount $TESTDIR/root 2>/dev/null || true
- [[ $LOOPDEV ]] && losetup -d $LOOPDEV || true
- return 0
+ _test_cleanup
}
test_run() {
--setup)
echo "TEST SETUP: $TEST_DESCRIPTION"
test_setup
+ test_setup_cleanup
;;
--clean)
echo "TEST CLEANUP: $TEST_DESCRIPTION"
test_cleanup
- rm -fr "$TESTDIR"
- rm -f "$STATEFILE"
;;
--all)
ret=0
- echo -n "TEST: $TEST_DESCRIPTION ";
+ echo -n "TEST: $TEST_DESCRIPTION "
(
- test_setup && test_run
- ret=$?
- test_cleanup
- rm -fr "$TESTDIR"
- rm -f "$STATEFILE"
- exit $ret
+ test_setup
+ test_setup_cleanup
+ test_run
) </dev/null >"$TESTLOG" 2>&1 || ret=$?
+ test_cleanup
if [ $ret -eq 0 ]; then
rm "$TESTLOG"
echo "[OK]"