1
0
mirror of https://github.com/systemd/systemd synced 2024-07-08 20:15:55 +00:00

mkosi: Changes to allow booting with sanitizers in mkosi

- Extra memory because ASAN needs it
- The environment variables to make the sanitizers more useful
- LD_PRELOAD because the ASAN DSO needs to be the first in the list
- The sanitizer library packages
- Disable syscall filters because they interfere with ASAN
- Disable systemd-hwdb-update because it's super slow when systemd-hwdb
  is built with sanitizers
- Take the value for meson's b_sanitize option from the SANITIZERS
  environment variable
This commit is contained in:
Daan De Meyer 2022-07-15 02:26:52 +02:00
parent 111ff5d511
commit 69d638e67e
10 changed files with 100 additions and 4 deletions

View File

@ -140,6 +140,11 @@ enabled that are suitable when hacking on systemd (such as internal
documentation consistency checks). Those are not useful when compiling for
distribution and can be disabled by setting `-Dmode=release`.
## Sanitizers in mkosi
See [Testing systemd using sanitizers](TESTING_WITH_SANITIZERS.md) for more information
on how to build with sanitizers enabled in mkosi.
## Fuzzers
systemd includes fuzzers in `src/fuzz/` that use libFuzzer and are automatically

View File

@ -13,6 +13,22 @@ This is mostly done automagically by various CI systems for each PR, but you may
want to do it locally as well. The process slightly varies depending on the
compiler you want to use and which part of the test suite you want to run.
## mkosi
To build with sanitizers in mkosi, create a file 20-local.conf in mkosi.default.d/ and add the following
contents:
```
[Content]
Environment=SANITIZERS=address,undefined
```
The value of `SANITIZERS` is passed directly to meson's `b_sanitize` option, See
https://mesonbuild.com/Builtin-options.html#base-options for the format expected by the option. Currently,
only the sanitizers supported by gcc can be used, which are `address` and `undefined`.
Note that this will only work with a recent version of mkosi (>= 14 or by running mkosi directly from source).
## gcc
gcc compiles in sanitizer libraries dynamically by default, so you need to get
the shared libraries first - on Fedora these are shipped as a separate packages

View File

@ -5,6 +5,9 @@ set -e
# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi).
# Simply invoke "mkosi" in the project directory to build an OS image.
ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:disable_coredump=0:use_madv_dontdump=1
UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
# On Fedora "ld" is (unfortunately — if you ask me) managed via
# "alternatives". Since we'd like to support building images in environments
# with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem
@ -61,7 +64,8 @@ if [ ! -f "$BUILDDIR"/build.ninja ] ; then
-D man=false \
-D translations=false \
-D version-tag="${VERSION_TAG}" \
-D mode=developer
-D mode=developer \
-D b_sanitize="${SANITIZERS:-none}"
fi
cd "$BUILDDIR"
@ -71,7 +75,15 @@ if [ "$WITH_TESTS" = 1 ] ; then
getent group $id >/dev/null || groupadd -g $id testgroup$id
done
ninja test
if [ -n "$SANITIZERS" ]; then
export ASAN_OPTIONS="$ASAN_OPTIONS"
export UBSAN_OPTIONS="$UBSAN_OPTIONS"
TIMEOUT_MULTIPLIER=3
else
TIMEOUT_MULTIPLIER=1
fi
meson test --timeout-multiplier=$TIMEOUT_MULTIPLIER
fi
cd "$SRCDIR"
@ -120,3 +132,42 @@ if [ -n "$CI_BUILD" ]; then
cp -v "$SRCDIR/test/mkosi-check-and-shutdown.sh" "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh"
chmod +x "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh"
fi
if [ -n "$SANITIZERS" ]; then
LD_PRELOAD=$(ldd $BUILDDIR/systemd | grep libasan.so | awk '{print $3}')
mkdir -p "$DESTDIR/etc/systemd/system.conf.d"
cat > "$DESTDIR/etc/systemd/system.conf.d/10-asan.conf" <<EOF
[Manager]
ManagerEnvironment=ASAN_OPTIONS=$ASAN_OPTIONS\\
UBSAN_OPTIONS=$UBSAN_OPTIONS\\
LD_PRELOAD=$LD_PRELOAD
DefaultEnvironment=ASAN_OPTIONS=$ASAN_OPTIONS\\
UBSAN_OPTIONS=$UBSAN_OPTIONS\\
LD_PRELOAD=$LD_PRELOAD
EOF
# ASAN logs to stderr by default. However, journald's stderr is connected to /dev/null, so we lose
# all the ASAN logs. To rectify that, let's connect journald's stdout to the console so that any
# sanitizer failures appear directly on the user's console.
mkdir -p "$DESTDIR/etc/systemd/system/systemd-journald.service.d"
cat > "$DESTDIR/etc/systemd/system/systemd-journald.service.d/10-stdout-tty.conf" <<EOF
[Service]
StandardOutput=tty
EOF
# Both systemd and util-linux's login call vhangup() on /dev/console which disconnects all users.
# This means systemd-journald can't log to /dev/console even if we configure `StandardOutput=tty`. As
# a workaround, we modify console-getty.service to disable systemd's vhangup() and disallow login
# from calling vhangup() so that journald's ASAN logs correctly end up in the console.
mkdir -p "$DESTDIR/etc/systemd/system/console-getty.service.d"
cat > "$DESTDIR/etc/systemd/system/console-getty.service.d/10-no-vhangup.conf" <<EOF
[Service]
TTYVHangup=no
CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
EOF
fi

View File

@ -6,6 +6,8 @@
Format=gpt_btrfs
Bootable=yes
HostonlyInitrd=yes
# Prevent ASAN warnings when building the image
Environment=ASAN_OPTIONS=verify_asan_link_order=false
[Packages]
BuildDirectory=mkosi.builddir
@ -16,6 +18,7 @@ SourceFileTransferFinal=copy-git-others
[Host]
QemuHeadless=yes
NetworkVeth=yes
QemuMem=2G
[Validation]
Password=

View File

@ -78,6 +78,8 @@ Packages=
e2fsprogs
# xxd is provided by the vim-common package
vim-common
libasan
libubsan
# Required to run systemd-networkd-tests.py
python3
iproute

View File

@ -74,6 +74,8 @@ Packages=
nano
strace
xxd
# Provides libasan/libubsan
gcc
# Required to run systemd-networkd-tests.py
python3
iproute2

View File

@ -77,6 +77,9 @@ Packages=
compsize
# xxd is provided by the vim-common package
vim-common
# Sanitizers
libasan
libubsan
# Required to run systemd-networkd-tests.py
python
iproute

View File

@ -75,3 +75,5 @@ Packages=
util-linux
# xxd is provided by the vim package
vim
# Provides libasan/libubsan
gcc

View File

@ -72,6 +72,8 @@ Packages=
nano
strace
xxd
# Provides libasan/libubsan
gcc
# Required to run systemd-networkd-tests.py
python3
iproute2

View File

@ -1,8 +1,18 @@
#!/bin/sh
# SPDX-License-Identifier: LGPL-2.1-or-later
if [ "$1" = "final" ] && command -v bootctl > /dev/null && [ -d "/efi" ]; then
bootctl install
if [ "$1" = "final" ]; then
if command -v bootctl > /dev/null && [ -d "/efi" ]; then
bootctl install
fi
if [ -n "$SANITIZERS" ]; then
# ASAN and syscall filters aren't compatible with each other.
find / -name '*.service' -type f -exec sed -i 's/^\(MemoryDeny\|SystemCall\)/# \1/' {} +
# `systemd-hwdb update` takes > 50s when built with sanitizers so let's not run it by default.
systemctl mask systemd-hwdb-update.service
fi
fi
# Temporary workaround until https://github.com/openSUSE/suse-module-tools/commit/158643414ddb8d8208016a5f03a4484d58944d7a