mirror of
https://github.com/systemd/systemd.git
synced 2026-08-13 17:08:14 +00:00
test: build the crashing test binary outside of the test
So we don't have to pull in gcc and other stuff into it.
Also, make the test itself a bit more robust and debug-able.
(cherry picked from commit 937f609b41)
This commit is contained in:
committed by
Zbigniew Jędrzejewski-Szmek
parent
94989a170d
commit
a0da62f2cb
@@ -276,6 +276,17 @@ executables += [
|
||||
'sources' : files('test-compress.c'),
|
||||
'link_with' : [libshared],
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-coredump-stacktrace.c'),
|
||||
'type' : 'manual',
|
||||
# This test intentionally crashes with SIGSEGV by dereferencing a NULL pointer
|
||||
# to generate a coredump with a predictable stack trace. To prevent sanitizers
|
||||
# from catching the error first let's disable them explicitly, and also always
|
||||
# build with minimal optimizations to make the stack trace predictable no matter
|
||||
# what we build the rest of systemd with
|
||||
'override_options' : ['b_sanitize=none', 'strip=false', 'debug=true'],
|
||||
'c_args' : ['-fno-sanitize=all', '-fno-optimize-sibling-calls', '-O1'],
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-cryptolib.c'),
|
||||
'dependencies' : libopenssl,
|
||||
|
||||
29
src/test/test-coredump-stacktrace.c
Normal file
29
src/test/test-coredump-stacktrace.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
/* This is a test program that intentionally segfaults so we can generate a
|
||||
* predictable-ish stack trace in tests. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
__attribute__((noinline))
|
||||
static void baz(int *x) {
|
||||
*x = rand();
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static void bar(void) {
|
||||
int * volatile x = NULL;
|
||||
|
||||
baz(x);
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
static void foo(void) {
|
||||
bar();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
foo();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -8,15 +8,13 @@ set -o pipefail
|
||||
|
||||
# Make sure the binary name fits into 15 characters
|
||||
CORE_TEST_BIN="/tmp/test-dump"
|
||||
CORE_STACKTRACE_TEST_BIN="/tmp/test-stacktrace-dump"
|
||||
MAKE_STACKTRACE_DUMP="/tmp/make-stacktrace-dump"
|
||||
CORE_TEST_UNPRIV_BIN="/tmp/test-usr-dump"
|
||||
MAKE_DUMP_SCRIPT="/tmp/make-dump"
|
||||
# Unset $PAGER so we don't have to use --no-pager everywhere
|
||||
export PAGER=
|
||||
|
||||
at_exit() {
|
||||
rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT" "$MAKE_STACKTRACE_DUMP"
|
||||
rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT"
|
||||
}
|
||||
|
||||
(! systemd-detect-virt -cq)
|
||||
@@ -251,30 +249,66 @@ systemd-run -t --property CoredumpFilter=default ls /tmp
|
||||
(! coredumpctl debug --debugger=/bin/true --debugger-arguments='"')
|
||||
|
||||
# Test for EnterNamespace= feature
|
||||
if pkgconf --atleast-version 0.192 libdw ; then
|
||||
# dwfl_set_sysroot() is supported only in libdw-0.192 or newer.
|
||||
cat >"$MAKE_STACKTRACE_DUMP" <<END
|
||||
#!/usr/bin/env bash
|
||||
mount -t tmpfs tmpfs /tmp
|
||||
gcc -xc -O0 -g -o $CORE_STACKTRACE_TEST_BIN - <<EOF
|
||||
void baz(void) { int *x = 0; *x = 42; }
|
||||
void bar(void) { baz(); }
|
||||
void foo(void) { bar(); }
|
||||
int main(void) { foo(); return 0;}
|
||||
#
|
||||
# dwfl_set_sysroot() is supported only in libdw-0.192 or newer.
|
||||
if pkgconf --atleast-version 0.192 libdw; then
|
||||
MAKE_STACKTRACE_DUMP="/tmp/make-stacktrace-dump"
|
||||
|
||||
# Simple script that mounts tmpfs on /tmp/ and copies the crashing test binary there, which in
|
||||
# combination with `unshare --mount` ensures the "outside" systemd-coredump process won't be able to
|
||||
# access the crashed binary (and hence won't be able to symbolize its stacktrace) unless
|
||||
# EnterNamespace=yes is used
|
||||
cat >"$MAKE_STACKTRACE_DUMP" <<\EOF
|
||||
#!/usr/bin/bash -eux
|
||||
|
||||
TARGET="/tmp/${1:?}"
|
||||
EC=0
|
||||
|
||||
# "Unhide" debuginfo in the namespace (see the comment below)
|
||||
test -d /usr/lib/debug/ && umount /usr/lib/debug/
|
||||
|
||||
mount -t tmpfs tmpfs /tmp/
|
||||
cp /usr/lib/systemd/tests/unit-tests/manual/test-coredump-stacktrace "$TARGET"
|
||||
|
||||
$TARGET || EC=$?
|
||||
if [[ $EC -ne 139 ]]; then
|
||||
echo >&2 "$TARGET didn't crash, this shouldn't happen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
$CORE_STACKTRACE_TEST_BIN
|
||||
END
|
||||
chmod +x "$MAKE_STACKTRACE_DUMP"
|
||||
|
||||
# Since the test-coredump-stacktrace binary is built together with rest of the systemd its debug symbols
|
||||
# might be part of debuginfo packages (if supported & built), and libdw will then use them to symbolize
|
||||
# the stacktrace even if it doesn't have access to the original crashing binary. Let's make the test
|
||||
# simpler and just "hide" the debuginfo data, so libdw is forced to access the target namespace to get
|
||||
# the necessary symbols
|
||||
test -d /usr/lib/debug/ && mount -t tmpfs tmpfs /usr/lib/debug/
|
||||
|
||||
mkdir -p /run/systemd/coredump.conf.d/
|
||||
printf '[Coredump]\nEnterNamespace=no' >/run/systemd/coredump.conf.d/99-enter-namespace.conf
|
||||
|
||||
unshare --pid --fork --mount-proc --mount --uts --ipc --net bash -c "$MAKE_STACKTRACE_DUMP" || :
|
||||
timeout 30 bash -c "until coredumpctl -1 info $CORE_STACKTRACE_TEST_BIN | grep -zvqE 'baz.*bar.*foo'; do sleep .2; done"
|
||||
unshare --pid --fork --mount-proc --mount --uts --ipc --net "$MAKE_STACKTRACE_DUMP" "test-stacktrace-not-symbolized"
|
||||
timeout 30 bash -c "until coredumpctl list -q --no-legend /tmp/test-stacktrace-not-symbolized; do sleep .2; done"
|
||||
coredumpctl info /tmp/test-stacktrace-not-symbolized | tee /tmp/not-symbolized.log
|
||||
(! grep -E "#[0-9]+ .* main " /tmp/not-symbolized.log)
|
||||
(! grep -E "#[0-9]+ .* foo " /tmp/not-symbolized.log)
|
||||
(! grep -E "#[0-9]+ .* bar " /tmp/not-symbolized.log)
|
||||
(! grep -E "#[0-9]+ .* baz " /tmp/not-symbolized.log)
|
||||
|
||||
printf '[Coredump]\nEnterNamespace=yes' >/run/systemd/coredump.conf.d/99-enter-namespace.conf
|
||||
unshare --pid --fork --mount-proc --mount --uts --ipc --net bash -c "$MAKE_STACKTRACE_DUMP" || :
|
||||
timeout 30 bash -c "until coredumpctl -1 info $CORE_STACKTRACE_TEST_BIN | grep -zqE 'baz.*bar.*foo'; do sleep .2; done"
|
||||
unshare --pid --fork --mount-proc --mount --uts --ipc --net "$MAKE_STACKTRACE_DUMP" "test-stacktrace-symbolized"
|
||||
timeout 30 bash -c "until coredumpctl list -q --no-legend /tmp/test-stacktrace-symbolized; do sleep .2; done"
|
||||
coredumpctl info /tmp/test-stacktrace-symbolized | tee /tmp/symbolized.log
|
||||
grep -E "#[0-9]+ .* main " /tmp/symbolized.log
|
||||
grep -E "#[0-9]+ .* foo " /tmp/symbolized.log
|
||||
grep -E "#[0-9]+ .* bar " /tmp/symbolized.log
|
||||
grep -E "#[0-9]+ .* baz " /tmp/symbolized.log
|
||||
|
||||
test -d /usr/lib/debug/ && umount /usr/lib/debug/
|
||||
rm -f "$MAKE_STACKTRACE_DUMP" /run/systemd/coredump.conf.d/99-enter-namespace.conf /tmp/{not-,}symbolized.log
|
||||
else
|
||||
echo "libdw doesn't not support setting sysroot, skipping EnterNamespace= test"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user