mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-23 14:27:37 -04:00
Add a shell test that verifies perf report handles truncated perf.data files gracefully — exiting with an error code rather than crashing with SIGSEGV or SIGABRT. The test records a simple workload, then truncates the resulting perf.data at four offsets that exercise different parsing stages: 8 bytes — file header magic only 64 bytes — partial file header (attr section incomplete) 256 bytes — into the first events (partial event headers) 75% size — mid-stream truncation (partial event data) For each truncation, perf report is run and the exit code is checked: - Exit code 0 (success) fails the test — a truncated file should never parse without error. - Crash signals are detected portably via kill -l, which maps the signal number to a name on the running system. This handles architectures where signal numbers differ (e.g. SIGBUS is 7 on x86/ARM but 10 on MIPS/SPARC). Core-dump and fatal signals (KILL, ILL, ABRT, BUS, FPE, SEGV, TRAP, SYS) fail the test. - Higher exit codes (200+) are perf's own negative-errno returns (e.g. -EINVAL = 234) and are expected. This exercises the bounds checking, minimum-size validation, and error propagation added by the preceding patches in this series. Testing it: root@number:~# perf test truncat 84: Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).: Ok root@number:~# perf test -vv truncat 84: Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).: --- start --- test child forked, pid 62890 ---- end(0) ---- 84: Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).: Ok root@number:~# Changes in v2: - Add SIGKILL to the list of fatal signals so OOM kills from resource exhaustion bugs are detected (Reported-by: sashiko-bot@kernel.org) Reviewed-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6-1m [ Fixed the SPDX on the line where 'perf test' expects the test description, reviewed by Ian Rogers ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
87 lines
2.8 KiB
Bash
Executable File
87 lines
2.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# Test that perf report handles truncated perf.data gracefully (no crash, no segfault — clean error exit).
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
#
|
|
# Exercises the bounds checking and minimum-size validation added
|
|
# by the perf-data-validation hardening series.
|
|
|
|
err=0
|
|
|
|
cleanup() {
|
|
[ -n "${perfdata}" ] && rm -f "${perfdata}" "${perfdata}.old"
|
|
rm -f "${truncated}" "${stderrfile}"
|
|
trap - EXIT TERM INT
|
|
}
|
|
trap 'cleanup; exit 1' TERM INT
|
|
trap cleanup EXIT
|
|
|
|
perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2
|
|
truncated=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2
|
|
stderrfile=$(mktemp /tmp/__perf_test.perf.data.XXXXX) || exit 2
|
|
|
|
# Record a simple workload
|
|
if ! perf record -o "${perfdata}" -- perf test -w noploop 2>/dev/null; then
|
|
echo "Skip: perf record failed"
|
|
cleanup
|
|
exit 2
|
|
fi
|
|
|
|
file_size=$(wc -c < "${perfdata}")
|
|
if [ "${file_size}" -lt 512 ]; then
|
|
echo "Skip: perf.data too small (${file_size} bytes)"
|
|
cleanup
|
|
exit 2
|
|
fi
|
|
|
|
# Test truncation at various offsets that exercise different
|
|
# parsing stages:
|
|
# 8 — file header magic only, no attrs or data
|
|
# 64 — partial file header (attr section incomplete)
|
|
# 256 — into the first events (partial event headers)
|
|
# 75% — mid-stream truncation (partial event data)
|
|
for cut_at in 8 64 256 $((file_size * 3 / 4)); do
|
|
if [ "${cut_at}" -ge "${file_size}" ]; then
|
|
continue
|
|
fi
|
|
dd if="${perfdata}" of="${truncated}" bs="${cut_at}" count=1 2>/dev/null
|
|
|
|
# perf report should exit with an error, not crash.
|
|
# Capture stderr to detect sanitizer violations.
|
|
perf report -i "${truncated}" --stdio > /dev/null 2> "${stderrfile}"
|
|
exit_code=$?
|
|
|
|
# A truncated file should never parse successfully
|
|
if [ ${exit_code} -eq 0 ]; then
|
|
echo "FAIL: perf report exited 0 (success) on ${cut_at}-byte truncated file — expected an error"
|
|
err=1
|
|
continue
|
|
fi
|
|
|
|
# Detect sanitizer violations — ASAN/MSAN/TSAN/UBSAN exit
|
|
# with code 1 by default, which would otherwise look like a
|
|
# clean error exit. Check stderr for their markers.
|
|
if grep -qE "^(==[0-9]+==ERROR:|SUMMARY: [A-Za-z]*Sanitizer)" "${stderrfile}" 2>/dev/null; then
|
|
sanitizer=$(grep -oE "(Address|Memory|Thread|UndefinedBehavior)Sanitizer" "${stderrfile}" | head -1)
|
|
echo "FAIL: perf report triggered ${sanitizer:-sanitizer} on ${cut_at}-byte truncated file"
|
|
err=1
|
|
continue
|
|
fi
|
|
|
|
# Detect crash signals portably — signal numbers differ
|
|
# across architectures (e.g. SIGBUS is 7 on x86/ARM but
|
|
# 10 on MIPS/SPARC). Use kill -l to map the number to a
|
|
# name on the running system.
|
|
if [ ${exit_code} -gt 128 ] && [ ${exit_code} -lt 200 ]; then
|
|
sig_name=$(kill -l $((exit_code - 128)) 2>/dev/null)
|
|
case ${sig_name} in
|
|
KILL|ILL|ABRT|BUS|FPE|SEGV|TRAP|SYS)
|
|
echo "FAIL: perf report crashed (SIG${sig_name}) on ${cut_at}-byte truncated file"
|
|
err=1
|
|
;;
|
|
esac
|
|
fi
|
|
done
|
|
|
|
cleanup
|
|
exit ${err}
|