2 # SPDX-License-Identifier: LGPL-2.1-or-later
6 # shellcheck source=test/units/util.sh
7 .
"$(dirname "$0")"/util.sh
9 # Make sure the binary name fits into 15 characters
10 CORE_TEST_BIN
="/tmp/test-dump"
11 CORE_STACKTRACE_TEST_BIN
="/tmp/test-stacktrace-dump"
12 MAKE_STACKTRACE_DUMP
="/tmp/make-stacktrace-dump"
13 CORE_TEST_UNPRIV_BIN
="/tmp/test-usr-dump"
14 MAKE_DUMP_SCRIPT
="/tmp/make-dump"
15 # Unset $PAGER so we don't have to use --no-pager everywhere
19 rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT" "$MAKE_STACKTRACE_DUMP"
22 (! systemd-detect-virt
-cq)
26 # To make all coredump entries stored in system.journal.
29 # Check that we're the ones to receive coredumps
30 sysctl kernel.core_pattern |
grep systemd-coredump
32 # Prepare "fake" binaries for coredumps, so we can properly exercise
33 # the matching stuff too
34 cp -vf /bin
/sleep "${CORE_TEST_BIN:?}"
35 cp -vf /bin
/sleep "${CORE_TEST_UNPRIV_BIN:?}"
36 # Simple script that spawns given "fake" binary and then kills it with
38 cat >"${MAKE_DUMP_SCRIPT:?}" <<\EOF
47 # Sync with the "fake" binary, so we kill it once it's fully forked off,
48 # otherwise we might kill it during fork and kernel would then report
49 # "wrong" binary name (i.e. $MAKE_DUMP_SCRIPT instead of $CORE_TEST_BIN).
50 # In this case, wait until the "fake" binary (sleep in this case) enters
51 # the "interruptible sleep" state, at which point it should be ready
54 read -ra self_stat
<"/proc/$pid/stat"
55 [[ "${self_stat[2]}" == S
]] && break
59 # This should always fail
62 chmod +x
"$MAKE_DUMP_SCRIPT"
65 [[ "$(id -u)" -eq 0 ]]
66 # Trigger a couple of coredumps
67 "$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGTRAP"
68 "$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT"
69 # In the tests we store the coredumps in journals, so let's generate a couple
70 # with Storage=external as well
71 mkdir
-p /run
/systemd
/coredump.conf.d
/
72 printf '[Coredump]\nStorage=external' >/run
/systemd
/coredump.conf.d
/99-external.conf
73 "$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGTRAP"
74 "$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT"
75 rm -fv /run
/systemd
/coredump.conf.d
/99-external.conf
76 # Wait a bit for the coredumps to get processed
77 timeout
30 bash
-c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
79 if cgroupfs_supports_user_xattrs
; then
80 # Make sure we can forward crashes back to containers
81 CONTAINER
="TEST-87-AUX-UTILS-VM-container"
83 mkdir
-p "/var/lib/machines/$CONTAINER"
84 mkdir
-p "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d"
85 # Bind-mounting /etc into the container kinda defeats the purpose of --volatile=,
86 # but we need the ASan-related overrides scattered across /etc
87 cat > "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d/override.conf" <<EOF
90 ExecStart=systemd-nspawn --quiet --link-journal=try-guest --keep-unit --machine=%i --boot \
91 --volatile=yes --directory=/ --bind-ro=/etc --inaccessible=/etc/machine-id
93 systemctl daemon-reload
95 [[ "$(systemd-detect-virt)" == "qemu" ]] && TIMEOUT
=120 || TIMEOUT
=60
97 machinectl start
"$CONTAINER"
98 timeout
"$TIMEOUT" bash
-xec "until systemd-run -M '$CONTAINER' -q --wait --pipe true; do sleep .5; done"
100 [[ "$(systemd-run -M "$CONTAINER" -q --wait --pipe coredumpctl list -q --no-legend /usr/bin/sleep | wc -l)" -eq 0 ]]
101 machinectl copy-to
"$CONTAINER" "$MAKE_DUMP_SCRIPT"
102 systemd-run
-M "$CONTAINER" -q --wait --pipe "$MAKE_DUMP_SCRIPT" "/usr/bin/sleep" "SIGABRT"
103 systemd-run
-M "$CONTAINER" -q --wait --pipe "$MAKE_DUMP_SCRIPT" "/usr/bin/sleep" "SIGTRAP"
104 # Wait a bit for the coredumps to get processed
105 timeout
30 bash
-c "while [[ \$(systemd-run -M $CONTAINER -q --wait --pipe coredumpctl list -q --no-legend /usr/bin/sleep | wc -l) -lt 2 ]]; do sleep 1; done"
107 machinectl stop
"$CONTAINER"
108 rm -rf "/var/lib/machines/$CONTAINER"
113 SYSTEMD_LOG_LEVEL
=debug coredumpctl
115 coredumpctl
--version
116 coredumpctl
--no-pager --no-legend
120 coredumpctl
--reverse
121 coredumpctl
-F COREDUMP_EXE
122 coredumpctl
--json=short | jq
123 coredumpctl
--json=pretty | jq
124 coredumpctl
--json=off
126 coredumpctl
--directory=/var
/log
/journal
127 coredumpctl
--file="/var/log/journal/$(</etc/machine-id)"/*.journal
128 coredumpctl
--since=@
0
129 coredumpctl
--since=yesterday
--until=tomorrow
130 # We should have a couple of externally stored coredumps
131 coredumpctl
--field=COREDUMP_FILENAME |
tee /tmp
/coredumpctl.out
132 grep "/var/lib/systemd/coredump/core" /tmp
/coredumpctl.out
133 rm -f /tmp
/coredumpctl.out
136 coredumpctl info
"$CORE_TEST_BIN"
137 coredumpctl info
/foo
/bar
/ /baz
"$CORE_TEST_BIN"
138 coredumpctl info
"${CORE_TEST_BIN##*/}"
139 coredumpctl info foo bar baz
"${CORE_TEST_BIN##*/}"
140 coredumpctl info COREDUMP_EXE
="$CORE_TEST_BIN"
141 coredumpctl info COREDUMP_EXE
=aaaaa COREDUMP_EXE
= COREDUMP_EXE
="$CORE_TEST_BIN"
143 coredumpctl debug
--debugger=/bin
/true
"$CORE_TEST_BIN"
144 SYSTEMD_DEBUGGER
=/bin
/true coredumpctl debug
"$CORE_TEST_BIN"
145 coredumpctl debug
--debugger=/bin
/true
--debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_BIN##*/}"
147 coredumpctl dump
"$CORE_TEST_BIN" >/tmp
/core.redirected
148 test -s /tmp
/core.redirected
149 coredumpctl dump
-o /tmp
/core.output
"${CORE_TEST_BIN##*/}"
150 test -s /tmp
/core.output
151 rm -f /tmp
/core.
{output
,redirected
}
154 # Related issue: https://github.com/systemd/systemd/issues/26912
155 UNPRIV_CMD
=(systemd-run
--user --wait --pipe -M "testuser@.host" --)
156 # Trigger a couple of coredumps as an unprivileged user
157 "${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
158 "${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"
159 # In the tests we store the coredumps in journals, so let's generate a couple
160 # with Storage=external as well
161 mkdir
-p /run
/systemd
/coredump.conf.d
/
162 printf '[Coredump]\nStorage=external' >/run
/systemd
/coredump.conf.d
/99-external.conf
163 "${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
164 "${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"
165 rm -fv /run
/systemd
/coredump.conf.d
/99-external.conf
166 # Wait a bit for the coredumps to get processed
167 timeout
30 bash
-c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_UNPRIV_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
169 # root should see coredumps from both binaries
170 coredumpctl info
"$CORE_TEST_UNPRIV_BIN"
171 coredumpctl info
"${CORE_TEST_UNPRIV_BIN##*/}"
172 # The test user should see only their own coredumps
173 "${UNPRIV_CMD[@]}" coredumpctl
174 "${UNPRIV_CMD[@]}" coredumpctl info
"$CORE_TEST_UNPRIV_BIN"
175 "${UNPRIV_CMD[@]}" coredumpctl info
"${CORE_TEST_UNPRIV_BIN##*/}"
176 (! "${UNPRIV_CMD[@]}" coredumpctl info
--all "$CORE_TEST_BIN")
177 (! "${UNPRIV_CMD[@]}" coredumpctl info
--all "${CORE_TEST_BIN##*/}")
178 # We should have a couple of externally stored coredumps
179 "${UNPRIV_CMD[@]}" coredumpctl
--field=COREDUMP_FILENAME |
tee /tmp
/coredumpctl.out
180 grep "/var/lib/systemd/coredump/core" /tmp
/coredumpctl.out
181 rm -f /tmp
/coredumpctl.out
183 "${UNPRIV_CMD[@]}" coredumpctl debug
--debugger=/bin
/true
"$CORE_TEST_UNPRIV_BIN"
184 "${UNPRIV_CMD[@]}" coredumpctl debug
--debugger=/bin
/true
--debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_UNPRIV_BIN##*/}"
186 "${UNPRIV_CMD[@]}" coredumpctl dump
"$CORE_TEST_UNPRIV_BIN" >/tmp
/core.redirected
187 test -s /tmp
/core.redirected
188 "${UNPRIV_CMD[@]}" coredumpctl dump
-o /tmp
/core.output
"${CORE_TEST_UNPRIV_BIN##*/}"
189 test -s /tmp
/core.output
190 rm -f /tmp
/core.
{output
,redirected
}
191 (! "${UNPRIV_CMD[@]}" coredumpctl dump
"$CORE_TEST_BIN" >/dev
/null
)
194 # Pass one of the existing journal coredump records to systemd-coredump and
195 # use our PID as the source to make matching the coredump later easier
196 # systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT HOSTNAME
197 journalctl
-b -n 1 --output=export --output-fields=MESSAGE
,COREDUMP COREDUMP_EXE
="/usr/bin/test-dump" |
198 /usr
/lib
/systemd
/systemd-coredump
--backtrace $$
0 0 6 1679509994 12345 mymachine
199 # Wait a bit for the coredump to get processed
200 timeout
30 bash
-c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -eq 0 ]]; do sleep 1; done"
201 coredumpctl info
"$$"
202 coredumpctl info COREDUMP_HOSTNAME
="mymachine"
204 # This used to cause a stack overflow
205 systemd-run
-t --property CoredumpFilter
=all
ls /tmp
206 systemd-run
-t --property CoredumpFilter
=default
ls /tmp
208 (! coredumpctl
--hello-world)
210 (! coredumpctl
-n -1)
211 (! coredumpctl
--file=/dev
/null
)
212 (! coredumpctl
--since=0)
213 (! coredumpctl
--until='')
214 (! coredumpctl
--since=today
--until=yesterday
)
215 (! coredumpctl
--directory=/ --root=/)
216 (! coredumpctl
--json=foo
)
217 (! coredumpctl
-F foo
-F bar
)
218 (! coredumpctl list
0)
219 (! coredumpctl list
-- -1)
220 (! coredumpctl list
'')
221 (! coredumpctl info
/..
/.~
=)
222 (! coredumpctl info
'')
223 (! coredumpctl dump
--output=/dev
/full
"$CORE_TEST_BIN")
224 (! coredumpctl dump
--output=/dev
/null
--output=/dev
/null
"$CORE_TEST_BIN")
225 (! coredumpctl debug
--debugger=/bin
/false
)
226 (! coredumpctl debug
--debugger=/bin
/true
--debugger-arguments='"')
228 # Test for EnterNamespace= feature
229 if pkgconf
--atleast-version 0.192 libdw
; then
230 # dwfl_set_sysroot() is supported only in libdw-0.192 or newer.
231 cat >"$MAKE_STACKTRACE_DUMP" <<END
233 mount -t tmpfs tmpfs /tmp
234 gcc -xc -O0 -g -o $CORE_STACKTRACE_TEST_BIN - <<EOF
235 void baz(void) { int *x = 0; *x = 42; }
236 void bar(void) { baz(); }
237 void foo(void) { bar(); }
238 int main(void) { foo(); return 0;}
240 $CORE_STACKTRACE_TEST_BIN
242 chmod +x
"$MAKE_STACKTRACE_DUMP"
244 mkdir
-p /run
/systemd
/coredump.conf.d
/
245 printf '[Coredump]\nEnterNamespace=no' >/run
/systemd
/coredump.conf.d
/99-enter-namespace.conf
247 unshare
--pid --fork --mount-proc --mount --uts --ipc --net /bin
/bash
-c "$MAKE_STACKTRACE_DUMP" ||
:
248 timeout
30 bash
-c "until coredumpctl -1 info $CORE_STACKTRACE_TEST_BIN | grep -zvqE 'baz.*bar.*foo'; do sleep .2; done"
250 printf '[Coredump]\nEnterNamespace=yes' >/run
/systemd
/coredump.conf.d
/99-enter-namespace.conf
251 unshare
--pid --fork --mount-proc --mount --uts --ipc --net /bin
/bash
-c "$MAKE_STACKTRACE_DUMP" ||
:
252 timeout
30 bash
-c "until coredumpctl -1 info $CORE_STACKTRACE_TEST_BIN | grep -zqE 'baz.*bar.*foo'; do sleep .2; done"
254 echo "libdw doesn't not support setting sysroot, skipping EnterNamespace= test"