Handle each DSM override failure before owned temporary cleanup

The retained race refusals still left manual temporary files after the command-double change. Check write, permission and atomic link operations individually rather than relying on the grouped chain to reach cleanup. Keep concurrent files/directories and all credentials intact; the same mandatory race assertions remain. Matching Go1.26.9 is now actually observed and the complete installer suite remains required.

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-10-12 15:00:47 +01:00
parent dc678bfd9d
commit b7b0eb0b01
5 changed files with 17 additions and 6 deletions
@@ -34,7 +34,9 @@ reload, exact unknown-job status and independent process absence establish
retirement. On unconfirmed retirement it is restored only if the original path
is still absent, leaving the manual override and all local recovery state;
atomic non-replacement links refuse concurrently created files or directories,
including during restore; the staged recovery copy is retained on conflict. Only confirmed retirement removes the staged config and manual
including during restore; the staged recovery copy is retained on conflict.
Override write, permission and link operations each have explicit checked
failure handling and remove only their owned non-credential temporary file. Only confirmed retirement removes the staged config and manual
before credential/state erasure. No credentials, arguments or config contents
are returned by these observations. Existing same-instance URL, exact record,
TLS, systemd/OpenRC/rc.d/SysV and state-directory ownership remain unchanged.
@@ -35,7 +35,9 @@ reload, exact unknown-job status and independent process absence establish
retirement. On unconfirmed retirement it is restored only if the original path
is still absent, leaving the manual override and all local recovery state;
atomic non-replacement links refuse concurrently created files or directories,
including during restore; the staged recovery copy is retained on conflict. Only confirmed retirement removes the staged config and manual
including during restore; the staged recovery copy is retained on conflict.
Override write, permission and link operations each have explicit checked
failure handling and remove only their owned non-credential temporary file. Only confirmed retirement removes the staged config and manual
before credential/state erasure. No credentials, arguments or config contents
are returned by these observations. Existing same-instance URL, exact record,
TLS, systemd/OpenRC/rc.d/SysV and state-directory ownership remain unchanged.
+9 -1
View File
@@ -1622,7 +1622,15 @@ quiesce_upstart_agent_for_removal() {
pending=$(mktemp "${override}.XXXXXX") || return 1
# Link without replacement: an override created concurrently is not
# ours to overwrite. The temporary file contains no credential.
if ! { printf 'manual\n' > "$pending" && chmod 644 "$pending" && ln -T -- "$pending" "$override"; }; then
if ! printf 'manual\n' > "$pending"; then
rm -f -- "$pending"
return 1
fi
if ! chmod 644 "$pending"; then
rm -f -- "$pending"
return 1
fi
if ! ln -T -- "$pending" "$override"; then
rm -f -- "$pending"
return 1
fi
@@ -212,8 +212,7 @@ ln() {
race_restore_config "$target"
fi
printf 'file:link\n' >> "$EVENTS"
# Capture the external exit explicitly: builtin command under errexit
# can otherwise terminate the wrapper before production handles failure.
# Preserve the actual external command exit for the production handler.
if builtin command ln "$@"; then return 0; else return $?; fi
}
mv() {
+1 -1
View File
@@ -8473,7 +8473,7 @@ func TestInstallSHUpstartTeardownRequiresObservedQuiescence(t *testing.T) {
cmd := exec.CommandContext(ctx, "python3", repoFile("scripts", "installtests", "agent_upstart_teardown.py"))
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("DSM Upstart removal controls: %v\n%s", err, output)
t.Fatalf("DSM Upstart retirement and owned temporary cleanup controls: %v\n%s", err, output)
}
for _, name := range []string{
"test_refused_manager_precedes_remote_and_state_erasure",