summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2022-07-15 02:26:52 +0200
committerDaan De Meyer <daan.j.demeyer@gmail.com>2022-07-18 16:54:56 +0200
commit69d638e67e5bfc5fedcae4072f144a4f7d798c9a (patch)
tree7609b870b6116e04516fb3bb2901d9f64e65434c
parent111ff5d5115cb2f49aba59da5dbdf96a28d0974d (diff)
downloadsystemd-69d638e67e5bfc5fedcae4072f144a4f7d798c9a.tar.gz
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
-rw-r--r--docs/HACKING.md5
-rw-r--r--docs/TESTING_WITH_SANITIZERS.md16
-rwxr-xr-xmkosi.build55
-rw-r--r--mkosi.default.d/10-systemd.conf3
-rw-r--r--mkosi.default.d/centos_epel/10-mkosi.centos_epel2
-rw-r--r--mkosi.default.d/debian/10-mkosi.debian2
-rw-r--r--mkosi.default.d/fedora/10-mkosi.fedora3
-rw-r--r--mkosi.default.d/opensuse/10-mkosi.opensuse2
-rw-r--r--mkosi.default.d/ubuntu/10-mkosi.ubuntu2
-rwxr-xr-xmkosi.postinst14
10 files changed, 100 insertions, 4 deletions
diff --git a/docs/HACKING.md b/docs/HACKING.md
index 9e5313e07a..a74d0468e5 100644
--- a/docs/HACKING.md
+++ b/docs/HACKING.md
@@ -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
diff --git a/docs/TESTING_WITH_SANITIZERS.md b/docs/TESTING_WITH_SANITIZERS.md
index 4f965c9617..642e1f19c9 100644
--- a/docs/TESTING_WITH_SANITIZERS.md
+++ b/docs/TESTING_WITH_SANITIZERS.md
@@ -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
diff --git a/mkosi.build b/mkosi.build
index 2be8fdbda1..27e5b1c65c 100755
--- a/mkosi.build
+++ b/mkosi.build
@@ -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
diff --git a/mkosi.default.d/10-systemd.conf b/mkosi.default.d/10-systemd.conf
index 08a03f489b..24b85ddd0b 100644
--- a/mkosi.default.d/10-systemd.conf
+++ b/mkosi.default.d/10-systemd.conf
@@ -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=
diff --git a/mkosi.default.d/centos_epel/10-mkosi.centos_epel b/mkosi.default.d/centos_epel/10-mkosi.centos_epel
index 42b3c11629..086fcdb555 100644
--- a/mkosi.default.d/centos_epel/10-mkosi.centos_epel
+++ b/mkosi.default.d/centos_epel/10-mkosi.centos_epel
@@ -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
diff --git a/mkosi.default.d/debian/10-mkosi.debian b/mkosi.default.d/debian/10-mkosi.debian
index 44e8521d9a..9b77b5b832 100644
--- a/mkosi.default.d/debian/10-mkosi.debian
+++ b/mkosi.default.d/debian/10-mkosi.debian
@@ -74,6 +74,8 @@ Packages=
nano
strace
xxd
+ # Provides libasan/libubsan
+ gcc
# Required to run systemd-networkd-tests.py
python3
iproute2
diff --git a/mkosi.default.d/fedora/10-mkosi.fedora b/mkosi.default.d/fedora/10-mkosi.fedora
index a6b58c7589..0314a2faab 100644
--- a/mkosi.default.d/fedora/10-mkosi.fedora
+++ b/mkosi.default.d/fedora/10-mkosi.fedora
@@ -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
diff --git a/mkosi.default.d/opensuse/10-mkosi.opensuse b/mkosi.default.d/opensuse/10-mkosi.opensuse
index 53fe2f3c93..b1ca381759 100644
--- a/mkosi.default.d/opensuse/10-mkosi.opensuse
+++ b/mkosi.default.d/opensuse/10-mkosi.opensuse
@@ -75,3 +75,5 @@ Packages=
util-linux
# xxd is provided by the vim package
vim
+ # Provides libasan/libubsan
+ gcc
diff --git a/mkosi.default.d/ubuntu/10-mkosi.ubuntu b/mkosi.default.d/ubuntu/10-mkosi.ubuntu
index 0a54547f87..dfb0ec0fd5 100644
--- a/mkosi.default.d/ubuntu/10-mkosi.ubuntu
+++ b/mkosi.default.d/ubuntu/10-mkosi.ubuntu
@@ -72,6 +72,8 @@ Packages=
nano
strace
xxd
+ # Provides libasan/libubsan
+ gcc
# Required to run systemd-networkd-tests.py
python3
iproute2
diff --git a/mkosi.postinst b/mkosi.postinst
index 6eddadfea8..8817818a94 100755
--- a/mkosi.postinst
+++ b/mkosi.postinst
@@ -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