1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-22 22:03:43 +03:00

test: split the ASan wrapper into smaller blocks and tidy it up a bit

No functional change (hopefully), just making it easier on the eyes.

(cherry picked from commit ba79e8c2ccdea132c2c0a820deb27c66a5aa6956)
(cherry picked from commit 91f08ecca311bf06d2fe74e9f5c94a0dfc973637)
(cherry picked from commit bf60262374a6300651659ae5e5c02e36776f29fd)
This commit is contained in:
Frantisek Sumsal 2023-05-25 15:31:48 +02:00 committed by Luca Boccassi
parent 61d72099d7
commit 30767c809c

View File

@ -255,8 +255,8 @@ IS_BUILT_WITH_COVERAGE=$(is_built_with_coverage && echo yes || echo no)
if get_bool "$IS_BUILT_WITH_ASAN"; then
STRIP_BINARIES=no
PATH_TO_INIT="$ROOTLIBDIR/systemd-under-asan"
SKIP_INITRD="${SKIP_INITRD:-yes}"
PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan
QEMU_MEM="${QEMU_MEM:-2G}"
QEMU_SMP="${QEMU_SMP:-4}"
@ -782,88 +782,96 @@ EOF
}
create_asan_wrapper() {
local asan_wrapper="$initdir/$ROOTLIBDIR/systemd-under-asan"
dinfo "Create ASan wrapper as '$asan_wrapper'"
local asan_wrapper default_asan_options default_ubsan_options default_environment
[[ -z "$ASAN_RT_PATH" ]] && dfatal "ASAN_RT_PATH is empty, but it shouldn't be"
# clang: install llvm-symbolizer to generate useful reports
# See: https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports
[[ "$ASAN_COMPILER" == "clang" ]] && image_install "llvm-symbolizer"
default_asan_options="${ASAN_OPTIONS:-strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1}"
default_ubsan_options="${UBSAN_OPTIONS:-print_stacktrace=1:print_summary=1:halt_on_error=1}"
cat >"$asan_wrapper" <<EOF
#!/usr/bin/env bash
if [[ "$ASAN_COMPILER" == "clang" ]]; then
# clang: install llvm-symbolizer to generate useful reports
# See: https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports
image_install "llvm-symbolizer"
set -x
# Let's add the ASan DSO's path to the dynamic linker's cache. This is pretty
# unnecessary for gcc & libasan, however, for clang this is crucial, as its
# runtime ASan DSO is in a non-standard (library) path.
mkdir -p "${initdir:?}/etc/ld.so.conf.d/"
echo "${ASAN_RT_PATH%/*}" >"${initdir:?}/etc/ld.so.conf.d/asan-path-override.conf"
fi
echo "ASan RT: $ASAN_RT_PATH"
if [[ ! -e "$ASAN_RT_PATH" ]]; then
echo >&2 "Couldn't find ASan RT at '$ASAN_RT_PATH', can't continue"
exit 1
fi
DEFAULT_ASAN_OPTIONS=${ASAN_OPTIONS:-strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1}
DEFAULT_UBSAN_OPTIONS=${UBSAN_OPTIONS:-print_stacktrace=1:print_summary=1:halt_on_error=1}
DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS"
# Create a simple environment file which can be included by systemd services
# that need it (i.e. services that utilize DynamicUser=true and bash, etc.)
cat >/usr/lib/systemd/systemd-asan-env <<INNER_EOF
# Create a simple environment file which can be included by systemd services
# that need it (i.e. services that utilize DynamicUser=true and bash, etc.)
cat >"${initdir:?}/usr/lib/systemd/systemd-asan-env" <<EOF
LD_PRELOAD=$ASAN_RT_PATH
ASAN_OPTIONS=$DEFAULT_ASAN_OPTIONS
ASAN_OPTIONS=$default_asan_options
LSAN_OPTIONS=detect_leaks=0
UBSAN_OPTIONS=$DEFAULT_UBSAN_OPTIONS
INNER_EOF
UBSAN_OPTIONS=$default_ubsan_options
EOF
# As right now bash is the PID 1, we can't expect PATH to have a sane value.
# Let's make one to prevent unexpected "<bin> not found" issues in the future
export PATH="/sbin:/bin:/usr/sbin:/usr/bin"
default_environment=(
"ASAN_OPTIONS='$default_asan_options'"
"UBSAN_OPTIONS='$default_ubsan_options'"
"ASAN_RT_PATH='$ASAN_RT_PATH'"
)
mountpoint -q /proc || mount -t proc proc /proc
mountpoint -q /sys || mount -t sysfs sysfs /sys
mount -o remount,rw /
mkdir -p "${initdir:?}/etc/systemd/system.conf.d/"
cat >"${initdir:?}/etc/systemd/system.conf.d/asan.conf" <<EOF
[Manager]
DefaultEnvironment=${default_environment[*]}
ManagerEnvironment=${default_environment[*]}
DefaultTimeoutStartSec=180s
DefaultStandardOutput=journal+console
EOF
DEFAULT_ENVIRONMENT="\$DEFAULT_ENVIRONMENT ASAN_RT_PATH=$ASAN_RT_PATH"
if [[ "$ASAN_COMPILER" == "clang" ]]; then
# Let's add the ASan DSO's path to the dynamic linker's cache. This is pretty
# unnecessary for gcc & libasan, however, for clang this is crucial, as its
# runtime ASan DSO is in a non-standard (library) path.
echo "${ASAN_RT_PATH%/*}" >/etc/ld.so.conf.d/asan-path-override.conf
ldconfig
fi
echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf
echo DefaultTimeoutStartSec=180s >>/etc/systemd/system.conf
echo DefaultStandardOutput=journal+console >>/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/'
# ASAN and syscall filters aren't compatible with each other.
find "${initdir:?}" -name '*.service' -type f -print0 | xargs -0 sed -i 's/^\(MemoryDeny\|SystemCall\)/#\1/'
mkdir -p "${initdir:?}/etc/systemd/system/systemd-journald.service.d/"
cat >"${initdir:?}/etc/systemd/system/systemd-journald.service.d/asan-env.conf" <<EOF
[Service]
# 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 UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:log_path=/systemd-journald.ubsan.log\n" >"\$JOURNALD_CONF_DIR/env.conf"
Environment=ASAN_OPTIONS=$default_asan_options:log_path=/systemd-journald.asan.log UBSAN_OPTIONS=$default_ubsan_options:log_path=/systemd-journald.ubsan.log
# Sometimes UBSan sends its reports to stderr regardless of what is specified in log_path
# Let's try to catch them by redirecting stderr (and stdout just in case) to a file
# See https://github.com/systemd/systemd/pull/12524#issuecomment-491108821
printf "[Service]\nStandardOutput=file:/systemd-journald.out\n" >"\$JOURNALD_CONF_DIR/out.conf"
# 90s isn't enough for some services to finish when literally everything is run
# under ASan+UBSan in containers, which, in turn, are run in VMs.
# Let's limit which environments such services should be executed in.
mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d
printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=240s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
# Let's override another hard-coded timeout that kicks in too early
mkdir -p /etc/systemd/system/systemd-journal-flush.service.d
printf "[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-journal-flush.service.d/timeout.conf
export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
exec "$ROOTLIBDIR/systemd" "\$@"
StandardOutput=file:/systemd-journald.out
EOF
# 90s isn't enough for some services to finish when literally everything is run
# under ASan+UBSan in containers, which, in turn, are run in VMs.
# Let's limit which environments such services should be executed in.
mkdir -p "${initdir:?}/etc/systemd/system/systemd-hwdb-update.service.d/"
cat >"${initdir:?}/etc/systemd/system/systemd-hwdb-update.service.d/asan.conf" <<EOF
[Unit]
ConditionVirtualization=container
[Service]
TimeoutSec=240s
EOF
# Let's override another hard-coded timeout that kicks in too early
mkdir -p "${initdir:?}/etc/systemd/system/systemd-journal-flush.service.d/"
cat >"${initdir:?}/etc/systemd/system/systemd-journal-flush.service.d/asan.conf" <<EOF
[Service]
TimeoutSec=180s
EOF
asan_wrapper="${initdir:?}/${PATH_TO_INIT:?}"
# Sanity check to make sure we don't overwrite something we shouldn't.
[[ "$asan_wrapper" =~ systemd-under-asan$ ]]
cat >"$asan_wrapper" <<EOF
#!/usr/bin/env bash
set -eux
export ${default_environment[@]}
[[ -n "\$ASAN_OPTIONS" && -n "\$UBSAN_OPTIONS" ]]
exec "$ROOTLIBDIR/systemd" "\$@"
EOF
chmod 0755 "$asan_wrapper"
}