ryantimwilson / rpms / systemd

Forked from rpms/systemd a month ago
Clone
8d419f
From 25338c37915521876c84bca196de50d73c3c17ea Mon Sep 17 00:00:00 2001
8d419f
From: Frantisek Sumsal <frantisek@sumsal.cz>
8d419f
Date: Mon, 13 Dec 2021 20:50:28 +0100
8d419f
Subject: [PATCH] test: fuzz our dbus interfaces with dfuzzer
8d419f
8d419f
(cherry picked from commit 354b3364aa63620a0f732bb8a6fe9332a4f550e4)
8d419f
8d419f
Related: #2087652
8d419f
---
8d419f
 test/TEST-21-DFUZZER/Makefile   |  1 +
8d419f
 test/TEST-21-DFUZZER/test.sh    | 24 +++++++++
8d419f
 test/test-functions             |  1 +
8d419f
 test/units/testsuite-21.service | 10 ++++
8d419f
 test/units/testsuite-21.sh      | 94 +++++++++++++++++++++++++++++++++
8d419f
 5 files changed, 130 insertions(+)
8d419f
 create mode 120000 test/TEST-21-DFUZZER/Makefile
8d419f
 create mode 100755 test/TEST-21-DFUZZER/test.sh
8d419f
 create mode 100644 test/units/testsuite-21.service
8d419f
 create mode 100755 test/units/testsuite-21.sh
8d419f
8d419f
diff --git a/test/TEST-21-DFUZZER/Makefile b/test/TEST-21-DFUZZER/Makefile
8d419f
new file mode 120000
8d419f
index 0000000000..e9f93b1104
8d419f
--- /dev/null
8d419f
+++ b/test/TEST-21-DFUZZER/Makefile
8d419f
@@ -0,0 +1 @@
8d419f
+../TEST-01-BASIC/Makefile
8d419f
\ No newline at end of file
8d419f
diff --git a/test/TEST-21-DFUZZER/test.sh b/test/TEST-21-DFUZZER/test.sh
8d419f
new file mode 100755
8d419f
index 0000000000..ecc04e368c
8d419f
--- /dev/null
8d419f
+++ b/test/TEST-21-DFUZZER/test.sh
8d419f
@@ -0,0 +1,24 @@
8d419f
+#!/usr/bin/env bash
8d419f
+# SPDX-License-Identifier: LGPL-2.1-or-later
8d419f
+set -e
8d419f
+
8d419f
+TEST_DESCRIPTION="Fuzz our D-Bus interfaces with dfuzzer"
8d419f
+TEST_NO_NSPAWN=1
8d419f
+TEST_SUPPORTING_SERVICES_SHOULD_BE_MASKED=0
8d419f
+QEMU_TIMEOUT="${QEMU_TIMEOUT:-1800}"
8d419f
+
8d419f
+# shellcheck source=test/test-functions
8d419f
+. "${TEST_BASE_DIR:?}/test-functions"
8d419f
+
8d419f
+command -v dfuzzer >/dev/null || exit 0
8d419f
+
8d419f
+test_append_files() {
8d419f
+    local workspace="${1:?}"
8d419f
+
8d419f
+    image_install dfuzzer /etc/dfuzzer.conf
8d419f
+
8d419f
+    # Enable all systemd-related services, including the D-Bus ones
8d419f
+    "$SYSTEMCTL" --root="${workspace:?}" preset-all
8d419f
+}
8d419f
+
8d419f
+do_test "$@"
8d419f
diff --git a/test/test-functions b/test/test-functions
8d419f
index 44f465c914..079a7249e4 100644
8d419f
--- a/test/test-functions
8d419f
+++ b/test/test-functions
8d419f
@@ -99,6 +99,7 @@ SYSTEMD_JOURNAL_REMOTE="${SYSTEMD_JOURNAL_REMOTE:-$(command -v "$BUILD_DIR/syste
8d419f
 SYSTEMD="${SYSTEMD:-$(command -v "$BUILD_DIR/systemd" || command -v "$ROOTLIBDIR/systemd")}"
8d419f
 SYSTEMD_NSPAWN="${SYSTEMD_NSPAWN:-$(command -v "$BUILD_DIR/systemd-nspawn" || command -v systemd-nspawn)}"
8d419f
 JOURNALCTL="${JOURNALCTL:-$(command -v "$BUILD_DIR/journalctl" || command -v journalctl)}"
8d419f
+SYSTEMCTL="${SYSTEMCTL:-$(command -v "$BUILD_DIR/systemctl" || command -v systemctl)}"
8d419f
 
8d419f
 TESTFILE="${BASH_SOURCE[1]}"
8d419f
 if [ -z "$TESTFILE" ]; then
8d419f
diff --git a/test/units/testsuite-21.service b/test/units/testsuite-21.service
8d419f
new file mode 100644
8d419f
index 0000000000..a5f77d07b4
8d419f
--- /dev/null
8d419f
+++ b/test/units/testsuite-21.service
8d419f
@@ -0,0 +1,10 @@
8d419f
+# SPDX-License-Identifier: LGPL-2.1-or-later
8d419f
+[Unit]
8d419f
+Description=Fuzz our D-Bus interfaces with dfuzzer
8d419f
+After=dbus.service multi-user.target
8d419f
+Wants=dbus.service multi-user.target
8d419f
+
8d419f
+[Service]
8d419f
+ExecStartPre=rm -f /failed /skipped /testok
8d419f
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
8d419f
+Type=oneshot
8d419f
diff --git a/test/units/testsuite-21.sh b/test/units/testsuite-21.sh
8d419f
new file mode 100755
8d419f
index 0000000000..43b5fb6f22
8d419f
--- /dev/null
8d419f
+++ b/test/units/testsuite-21.sh
8d419f
@@ -0,0 +1,94 @@
8d419f
+#!/usr/bin/env bash
8d419f
+# SPDX-License-Identifier: LGPL-2.1-or-later
8d419f
+set -eux
8d419f
+set -o pipefail
8d419f
+
8d419f
+# Save the end.service state before we start fuzzing, as it might get changed
8d419f
+# on the fly by one of the fuzzers
8d419f
+systemctl list-jobs | grep -F 'end.service' && SHUTDOWN_AT_EXIT=1 || SHUTDOWN_AT_EXIT=0
8d419f
+
8d419f
+at_exit() {
8d419f
+    # "Safety net" - check for any coredumps which might have not caused dfuzzer
8d419f
+    # to stop & return an error (we need to do this now before truncating the
8d419f
+    # journal)
8d419f
+    # TODO: check fo ASan/UBSan errors
8d419f
+    local found_cd=0
8d419f
+    while read -r exe; do
8d419f
+        coredumctl info "$exe"
8d419f
+        found_cd=1
8d419f
+    done < <(coredumpctl -F COREDUMP_EXE | sort -u)
8d419f
+    [[ $found_cd -eq 0 ]] || exit 1
8d419f
+
8d419f
+    # We have to call the end.service explicitly even if it's specified on
8d419f
+    # the kernel cmdline via systemd.wants=end.service, since dfuzzer calls
8d419f
+    # org.freedesktop.systemd1.Manager.ClearJobs() which drops the service
8d419f
+    # from the queue
8d419f
+    [[ $SHUTDOWN_AT_EXIT -ne 0 ]] && systemctl start --job-mode=flush end.service
8d419f
+}
8d419f
+
8d419f
+trap at_exit EXIT
8d419f
+
8d419f
+systemctl log-level info
8d419f
+
8d419f
+# TODO
8d419f
+#   * check for possibly newly introduced buses?
8d419f
+BUS_LIST=(
8d419f
+    org.freedesktop.home1
8d419f
+    org.freedesktop.hostname1
8d419f
+    org.freedesktop.import1
8d419f
+    org.freedesktop.locale1
8d419f
+    org.freedesktop.login1
8d419f
+    org.freedesktop.machine1
8d419f
+    org.freedesktop.network1
8d419f
+    org.freedesktop.portable1
8d419f
+    org.freedesktop.resolve1
8d419f
+    org.freedesktop.systemd1
8d419f
+    org.freedesktop.timedate1
8d419f
+    org.freedesktop.timesync1
8d419f
+)
8d419f
+
8d419f
+# systemd-oomd requires PSI
8d419f
+if tail -n +1 /proc/pressure/{cpu,io,memory}; then
8d419f
+    BUS_LIST+=(org.freedesktop.oom1)
8d419f
+fi
8d419f
+
8d419f
+SESSION_BUS_LIST=(
8d419f
+    org.freedesktop.systemd1
8d419f
+)
8d419f
+
8d419f
+# Maximum payload size generated by dfuzzer (in bytes) - default: 50K
8d419f
+PAYLOAD_MAX=50000
8d419f
+# Tweak the maximum payload size if we're running under sanitizers, since
8d419f
+# with larger payloads we start hitting reply timeouts
8d419f
+if [[ -v ASAN_OPTIONS || -v UBSAN_OPTIONS ]]; then
8d419f
+    PAYLOAD_MAX=10000 # 10K
8d419f
+fi
8d419f
+
8d419f
+# Overmount /var/lib/machines with a size-limited tmpfs, as fuzzing
8d419f
+# the org.freedesktop.machine1 stuff makes quite a mess
8d419f
+mount -t tmpfs -o size=50M tmpfs /var/lib/machines
8d419f
+
8d419f
+# Fuzz both the system and the session buses (where applicable)
8d419f
+for bus in "${BUS_LIST[@]}"; do
8d419f
+    echo "Bus: $bus (system)"
8d419f
+    systemd-run --pipe --wait \
8d419f
+                -- dfuzzer -v -b "$PAYLOAD_MAX" -n "$bus"
8d419f
+
8d419f
+    # Let's reload the systemd daemon to test (de)serialization as well
8d419f
+    systemctl daemon-reload
8d419f
+done
8d419f
+
8d419f
+umount /var/lib/machines
8d419f
+
8d419f
+for bus in "${SESSION_BUS_LIST[@]}"; do
8d419f
+    echo "Bus: $bus (session)"
8d419f
+    systemd-run --machine 'testuser@.host' --user --pipe --wait \
8d419f
+                -- dfuzzer -v -b "$PAYLOAD_MAX" -n "$bus"
8d419f
+
8d419f
+    # Let's reload the systemd user daemon to test (de)serialization as well
8d419f
+    systemctl --machine 'testuser@.host' --user daemon-reload
8d419f
+done
8d419f
+
8d419f
+echo OK >/testok
8d419f
+
8d419f
+exit 0