1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-23 10:50:16 +03:00

Merge pull request #24025 from DaanDeMeyer/mkosi-sanitizers

mkosi: Changes to allow booting with sanitizers in mkosi
This commit is contained in:
Evgeny Vereshchagin 2022-07-18 19:24:51 +03:00 committed by GitHub
commit e99e4e4fec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 143 additions and 36 deletions

View File

@ -66,7 +66,7 @@ reuse the host's package cache. To do this, create a mkosi override file in
mkosi.default.d/ (e.g 20-local.conf) and add the following contents:
```
[Packages]
[Content]
Cache=<full-path-to-package-manager-cache> # (e.g. /var/cache/dnf)
```
@ -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
@ -224,7 +229,7 @@ mkosi's config. The easiest way to set the option is to create a file 20-local.c
add the following contents:
```
[Packages]
[Content]
IncludeDirectory=mkosi.includedir
```
@ -233,7 +238,7 @@ We already configured clangd to map any paths in /usr/include in the build image
host in the mkosi-clangd.sh script.
We also need to make sure clangd is installed in the build image. To have mkosi install clangd in the build
image, edit the 20-local.conf file we created earlier and add the following contents under the `[Packages]`
image, edit the 20-local.conf file we created earlier and add the following contents under the `[Content]`
section:
```

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
@ -49,10 +52,10 @@ if [ ! -f "$BUILDDIR"/build.ninja ] ; then
init_path=$(realpath /sbin/init 2>/dev/null)
if [ -z "$init_path" ] ; then
rootprefix=""
rootprefix=""
else
rootprefix=${init_path%/lib/systemd/systemd}
rootprefix=/${rootprefix#/}
rootprefix=${init_path%/lib/systemd/systemd}
rootprefix=/${rootprefix#/}
fi
meson "$BUILDDIR" \
@ -60,7 +63,9 @@ if [ ! -f "$BUILDDIR"/build.ninja ] ; then
-D "rootprefix=$rootprefix" \
-D man=false \
-D translations=false \
-D version-tag="${VERSION_TAG}"
-D version-tag="${VERSION_TAG}" \
-D mode=developer \
-D b_sanitize="${SANITIZERS:-none}"
fi
cd "$BUILDDIR"
@ -70,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"
@ -90,32 +103,71 @@ Kernel \r on an \m (\l)
EOF
if [ -n "$IMAGE_ID" ] ; then
mkdir -p "$DESTDIR"/usr/lib
sed -n \
-e '/^IMAGE_ID=/!p' \
-e "\$aIMAGE_ID=$IMAGE_ID" <"/usr/lib/os-release" >"${DESTDIR}/usr/lib/os-release"
mkdir -p "$DESTDIR"/usr/lib
sed -n \
-e '/^IMAGE_ID=/!p' \
-e "\$aIMAGE_ID=$IMAGE_ID" <"/usr/lib/os-release" >"${DESTDIR}/usr/lib/os-release"
OSRELEASEFILE="$DESTDIR"/usr/lib/os-release
OSRELEASEFILE="$DESTDIR"/usr/lib/os-release
else
OSRELEASEFILE=/usr/lib/os-release
OSRELEASEFILE=/usr/lib/os-release
fi
if [ -n "$IMAGE_VERSION" ] ; then
mkdir -p "$DESTDIR"/usr/lib
sed -n \
-e '/^IMAGE_VERSION=/!p' \
-e "\$aIMAGE_VERSION=$IMAGE_VERSION" <$OSRELEASEFILE >"/tmp/os-release.tmp"
mkdir -p "$DESTDIR"/usr/lib
sed -n \
-e '/^IMAGE_VERSION=/!p' \
-e "\$aIMAGE_VERSION=$IMAGE_VERSION" <$OSRELEASEFILE >"/tmp/os-release.tmp"
cat /tmp/os-release.tmp > "$DESTDIR"/usr/lib/os-release
rm /tmp/os-release.tmp
cat /tmp/os-release.tmp > "$DESTDIR"/usr/lib/os-release
rm /tmp/os-release.tmp
fi
# If $CI_BUILD is set, copy over the CI service which executes a service check
# after boot and then shuts down the machine
if [ -n "$CI_BUILD" ]; then
mkdir -p "$DESTDIR/usr/lib/systemd/system"
cp -v "$SRCDIR/test/mkosi-check-and-shutdown.service" "$DESTDIR/usr/lib/systemd/system/mkosi-check-and-shutdown.service"
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"
mkdir -p "$DESTDIR/usr/lib/systemd/system"
cp -v "$SRCDIR/test/mkosi-check-and-shutdown.service" "$DESTDIR/usr/lib/systemd/system/mkosi-check-and-shutdown.service"
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,8 +6,10 @@
Format=gpt_btrfs
Bootable=yes
HostonlyInitrd=yes
# Prevent ASAN warnings when building the image
Environment=ASAN_OPTIONS=verify_asan_link_order=false
[Packages]
[Content]
BuildDirectory=mkosi.builddir
Cache=mkosi.cache
InstallDirectory=mkosi.installdir
@ -15,7 +17,8 @@ SourceFileTransferFinal=copy-git-others
[Host]
QemuHeadless=yes
NetworkVeth=yes
Netdev=yes
QemuMem=2G
[Validation]
Password=

View File

@ -8,7 +8,7 @@
[Distribution]
Distribution=arch
[Packages]
[Content]
BuildPackages=
acl
bzip2
@ -63,6 +63,8 @@ Packages=
# For testing systemd's zsh completion scripts
# Run `autoload -Uz compinit; compinit` from a zsh shell in the booted image to enable completions.
zsh
# xxd is provided by the vim package
vim
# Required to run systemd-networkd-tests.py
python
iproute

View File

@ -10,7 +10,7 @@ Distribution=centos_epel
Format=gpt_xfs
HostonlyInitrd=no
[Packages]
[Content]
BuildPackages=
diffutils
docbook-style-xsl
@ -76,6 +76,10 @@ Packages=
less
netcat
e2fsprogs
# xxd is provided by the vim-common package
vim-common
libasan
libubsan
# Required to run systemd-networkd-tests.py
python3
iproute

View File

@ -7,7 +7,7 @@
Distribution=debian
Release=testing
[Packages]
[Content]
BuildPackages=
acl
clang
@ -73,6 +73,9 @@ Packages=
locales
nano
strace
xxd
# Provides libasan/libubsan
gcc
# Required to run systemd-networkd-tests.py
python3
iproute2

View File

@ -7,7 +7,7 @@
Distribution=fedora
Release=36
[Packages]
[Content]
BuildPackages=
diffutils
docbook-style-xsl
@ -75,6 +75,11 @@ Packages=
netcat
e2fsprogs
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

@ -7,7 +7,7 @@
Distribution=opensuse
Release=tumbleweed
[Packages]
[Content]
BuildPackages=
docbook-xsl-stylesheets
fdupes
@ -73,3 +73,7 @@ Packages=
nano
strace
util-linux
# xxd is provided by the vim package
vim
# Provides libasan/libubsan
gcc

View File

@ -5,10 +5,10 @@
[Distribution]
Distribution=ubuntu
Release=focal
Release=jammy
Repositories=main,universe
[Packages]
[Content]
BuildPackages=
acl
docbook-xml
@ -71,6 +71,9 @@ Packages=
locales
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; 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

View File

@ -21,7 +21,7 @@ Output=networkd-test.raw
[Partitions]
RootSize=3G
[Packages]
[Content]
BuildPackages=
audit-libs-devel
bzip2-devel