fix: revalidate exiting demo anchors

This commit is contained in:
golem
2026-08-21 05:12:50 -06:00
parent a28ad76868
commit eb2fd5245a
2 changed files with 193 additions and 22 deletions
+30 -17
View File
@@ -104,10 +104,12 @@ demo_has_exact_tail() {
demo_command_matches() {
local root=$1 pid=$2 kind=$3 expected executable interpreter entry_index
local -a arguments=()
[[ -r "/proc/$pid/cmdline" && -e "/proc/$pid/exe" ]] || return 1
{ mapfile -d '' -t arguments <"/proc/$pid/cmdline"; } 2>/dev/null || return 1
((${#arguments[@]} > 0)) || return 1
executable=$(readlink -f -- "/proc/$pid/exe" 2>/dev/null) || return 1
# Status 2 means /proc became unreadable while identity was being checked.
# Status 1 remains a definitive command mismatch.
[[ -r "/proc/$pid/cmdline" && -e "/proc/$pid/exe" ]] || return 2
{ mapfile -d '' -t arguments <"/proc/$pid/cmdline"; } 2>/dev/null || return 2
((${#arguments[@]} > 0)) || return 2
executable=$(readlink -f -- "/proc/$pid/exe" 2>/dev/null) || return 2
if [[ "$kind" == anvil ]]; then
expected=$(demo_resolve_command anvil) || return 1
@@ -203,16 +205,20 @@ demo_collect_group_members() {
}
demo_anchor_allows_signal() {
local root=$1 kind=$2 leader=$3 expected_start=$4 expected_pgid=$5 identity_mode=${6:-validated} state start pgid sid
if ! demo_read_process_identity "$leader" state start pgid sid; then return 0; fi
[[ "$start" == "$expected_start" && "$pgid" == "$expected_pgid" && "$sid" == "$expected_pgid" ]] || return 1
[[ "$state" == Z ]] && return 0
[[ "$identity_mode" == raw ]] && return 0
demo_process_has_command_line "$leader" || return 0
if demo_command_matches "$root" "$leader" "$kind"; then return 0; fi
if ! demo_read_process_identity "$leader" state start pgid sid; then return 0; fi
[[ "$state" == Z ]] && return 0
[[ "$start" == "$expected_start" && "$pgid" == "$expected_pgid" && "$sid" == "$expected_pgid" ]] || return 1
local root=$1 kind=$2 leader=$3 expected_start=$4 expected_pgid=$5 identity_mode=${6:-validated}
local state start pgid sid command_status attempt
local attempts=${DEMO_ANCHOR_RECHECK_ATTEMPTS:-10} interval=${DEMO_ANCHOR_RECHECK_INTERVAL:-0.01}
demo_is_uint "$attempts" && ((10#$attempts > 0)) || attempts=10
[[ "$interval" =~ ^[0-9]+([.][0-9]+)?$ ]] || interval=0.01
for ((attempt = 0; attempt < attempts; attempt++)); do
if ! demo_read_process_identity "$leader" state start pgid sid; then return 0; fi
[[ "$start" == "$expected_start" && "$pgid" == "$expected_pgid" && "$sid" == "$expected_pgid" ]] || return 1
[[ "$state" == Z ]] && return 0
[[ "$identity_mode" == raw ]] && return 0
if demo_command_matches "$root" "$leader" "$kind"; then return 0; else command_status=$?; fi
((command_status == 2)) || return 1
if ((attempt + 1 < attempts)); then sleep "$interval"; fi
done
return 1
}
@@ -221,10 +227,11 @@ demo_signal_member() {
if ! demo_read_process_identity "$pid" state start pgid sid; then return 0; fi
[[ "$state" != Z ]] || return 0
[[ "$start" == "$expected_start" && "$pgid" == "$expected_pgid" && "$sid" == "$expected_sid" ]] || return 2
if kill -"$signal" -- "$pid"; then return 0; else signal_status=$?; fi
if kill -"$signal" -- "$pid" 2>/dev/null; then return 0; else signal_status=$?; fi
if ! demo_read_process_identity "$pid" state start pgid sid; then return 0; fi
[[ "$state" != Z ]] || return 0
[[ "$start" == "$expected_start" && "$pgid" == "$expected_pgid" && "$sid" == "$expected_sid" ]] || return 0
printf 'Failed to signal unchanged live PID %s with %s\n' "$pid" "$signal" >&2
return "$signal_status"
}
@@ -255,13 +262,19 @@ demo_stop_owned_session() {
for member in "${members[@]}"; do
IFS=: read -r member_pid member_start <<<"$member"
[[ "$member_pid" != "$leader" ]] || continue
demo_anchor_allows_signal "$root" "$kind" "$leader" "$expected_start" "$expected_pgid" "$identity_mode" || return 1
if ! demo_anchor_allows_signal "$root" "$kind" "$leader" "$expected_start" "$expected_pgid" "$identity_mode"; then
printf 'Refusing TERM: %s leader identity changed or remained unverifiable\n' "$kind" >&2
return 1
fi
demo_signal_member "$member_pid" "$member_start" "$expected_pgid" "$expected_pgid" TERM || return 1
done
for member in "${members[@]}"; do
IFS=: read -r member_pid member_start <<<"$member"
[[ "$member_pid" == "$leader" ]] || continue
demo_anchor_allows_signal "$root" "$kind" "$leader" "$expected_start" "$expected_pgid" "$identity_mode" || return 1
if ! demo_anchor_allows_signal "$root" "$kind" "$leader" "$expected_start" "$expected_pgid" "$identity_mode"; then
printf 'Refusing TERM: %s leader identity changed or remained unverifiable\n' "$kind" >&2
return 1
fi
demo_signal_member "$member_pid" "$member_start" "$expected_pgid" "$expected_pgid" TERM || return 1
done
for ((result = 0; result < ${DEMO_TERM_WAIT_ATTEMPTS:-50}; result++)); do