From: Pengfei Li <[email protected]> Verify both enforcement points for the global-instance-only stackmap option.
Require options/stackmap and stack_map on the top-level instance. Read a shared-kernel random UUID from /proc/sys/kernel/random/uuid and combine it with ftracetest's $PID to create collision-resistant owned and foreign secondary-instance names, including across PID namespaces. Verify that neither the option nor any stack_map node appears in the owned instance. Also require writing stackmap through its aggregate trace_options file to fail and leave the option unset. Create the foreign instance as a sentinel. Remove the owned instance explicitly and verify the sentinel remains, proving that cleanup does not remove unrelated instances. Defer signal exit across each mkdir and ownership assignment so cleanup removes a directory only after this invocation has created it. Put mkdir in an if condition so ftracetest's errexit mode cannot bypass return-code handling, the explicit failure path, or ownership bookkeeping. Track both directories separately and remove only those created by this test. Keep the auxiliary stack_map_stat and stack_map_bin nodes optional on the global side. Signed-off-by: Pengfei Li <[email protected]> --- .../test.d/ftrace/stackmap-instance-gate.tc | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/ftrace/stackmap-instance-gate.tc diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/stackmap-instance-gate.tc b/tools/testing/selftests/ftrace/test.d/ftrace/stackmap-instance-gate.tc new file mode 100644 index 000000000000..818dbb7bfeb8 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/stackmap-instance-gate.tc @@ -0,0 +1,114 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - stackmap option is gated to the top-level trace instance +# requires: stack_map options/stackmap instances + +# The 'stackmap' option is added to TOP_LEVEL_TRACE_FLAGS, matching the +# convention used for global-only options like 'printk' and 'record-cmd'. +# Verify that: +# 1. The global instance exposes options/stackmap and the required +# stack_map node. stack_map_stat and stack_map_bin are auxiliary and +# may be absent if their tracefs creation failed. +# 2. A newly created secondary instance under instances/ does NOT expose +# options/stackmap or any stack_map* nodes. + +fail() { + echo "FAIL: $1" + exit_fail +} + +instance_token=$(cat /proc/sys/kernel/random/uuid 2>/dev/null) || { + echo "could not obtain a collision-resistant instance token" + exit_unresolved +} +[ -n "$instance_token" ] || exit_unresolved +owned_instance=stackmap_gate_owned_${PID}_${instance_token} +owned_dir=instances/$owned_instance +foreign_instance=stackmap_gate_foreign_${PID}_${instance_token} +foreign_dir=instances/$foreign_instance +owned_created=0 +foreign_created=0 + +remove_owned() { + if [ "$owned_created" -eq 1 ]; then + rmdir "$owned_dir" || return 1 + owned_created=0 + fi +} + +cleanup() { + if [ "$owned_created" -eq 1 ]; then + rmdir "$owned_dir" 2>/dev/null || : + fi + if [ "$foreign_created" -eq 1 ]; then + rmdir "$foreign_dir" 2>/dev/null || : + fi +} +trap cleanup EXIT +trap 'exit 1' HUP INT TERM + +# 1. Global instance must expose the option and required map node +test -e options/stackmap || fail "options/stackmap missing on global instance" +test -e stack_map || fail "stack_map missing on global instance" + +# 2. Create a foreign sentinel and an owned secondary instance. Defer signal +# exit across each mkdir and ownership assignment: cleanup must remove a path +# only after this invocation has successfully created it. +interrupted=0 +trap 'interrupted=1' HUP INT TERM +create_rc=0 +if mkdir "$foreign_dir"; then + foreign_created=1 +else + create_rc=$? +fi +trap 'exit 1' HUP INT TERM +[ "$interrupted" -eq 0 ] || exit 1 +[ "$create_rc" -eq 0 ] || fail "could not create foreign sentinel instance" + +interrupted=0 +trap 'interrupted=1' HUP INT TERM +create_rc=0 +if mkdir "$owned_dir"; then + owned_created=1 +else + create_rc=$? +fi +trap 'exit 1' HUP INT TERM +[ "$interrupted" -eq 0 ] || exit 1 +[ "$create_rc" -eq 0 ] || fail "could not create secondary instance" + +if [ -e "$owned_dir/options/stackmap" ]; then + fail "secondary instance unexpectedly exposes options/stackmap" +fi + +for f in stack_map stack_map_stat stack_map_bin; do + if [ -e "$owned_dir/$f" ]; then + fail "secondary instance unexpectedly has $f" + fi +done + +# 3. The aggregate trace_options file still reaches set_tracer_flag(), +# so writing 'stackmap' there must be rejected on a secondary +# instance. Otherwise the bit could appear set in trace_options +# while the hot path silently falls back to a full stack trace +# (tr->stackmap == NULL). +if echo stackmap > "$owned_dir/trace_options" 2>/dev/null; then + fail "secondary instance accepted 'echo stackmap > trace_options'" +fi +if grep -qw stackmap "$owned_dir/trace_options"; then + fail "secondary instance trace_options reports stackmap as set" +fi + +remove_owned || fail "could not remove owned secondary instance" +if [ -e "$owned_dir" ]; then + fail "owned secondary instance still exists after removal" +fi +if [ ! -d "$foreign_dir" ]; then + fail "owned cleanup removed foreign sentinel instance" +fi +rmdir "$foreign_dir" || fail "could not remove foreign sentinel instance" +foreign_created=0 + +echo "stackmap option gating to top-level instance works" +exit 0 -- 2.34.1
