[deckhouse-cli] fix macOS SIGKILL by installing the binary atomically - #430
Open
nevermarine wants to merge 1 commit into
Open
[deckhouse-cli] fix macOS SIGKILL by installing the binary atomically#430nevermarine wants to merge 1 commit into
nevermarine wants to merge 1 commit into
Conversation
The installer overwrote the binary in place with `cp` over the existing target path, which keeps the same inode. On macOS this leaves the kernel holding a stale code-signing validation for the previous contents of the ad-hoc signed binary, so an updated d8 is killed with SIGKILL on exec even though `codesign --verify` still passes. Copy to a temporary file next to the target and rename it into place so the new binary always gets a fresh inode. Signed-off-by: Maksim Fedotov <[email protected]>
nevermarine
force-pushed
the
fix/install/atomic-binary-replace
branch
from
July 31, 2026 10:06
af1f975 to
23146b5
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the tools/install.sh installer to avoid macOS (Apple Silicon) SIGKILL after in-place upgrades by installing the d8 binary via atomic replacement (rename()), preventing stale kernel code-signing cache issues.
Changes:
- Replace in-place
cpoverwrite with acpto a temporary sibling file andmv -finto place (atomic install). - Apply the atomic install approach to both sudo and non-sudo install paths.
Suppressed comments (1)
tools/install.sh:404
- Same issue as the sudo branch: if
${target_path}.tmp.$$already exists,cpwill truncate it in-place and keep its inode, which can defeat the “fresh inode via rename” guarantee. Remove any pre-existing temp file (or usemktemp) and store the temp path in a variable to avoid repetition.
cp "$binary_path" "${target_path}.tmp.$$"
chmod +x "${target_path}.tmp.$$"
mv -f "${target_path}.tmp.$$" "$target_path"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+391
to
+393
| sudo cp "$binary_path" "${target_path}.tmp.$$" | ||
| sudo chmod +x "${target_path}.tmp.$$" | ||
| sudo mv -f "${target_path}.tmp.$$" "$target_path" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On macOS (Apple Silicon), after the installer reinstalls/updates
d8, the binary is killed withSIGKILLon every invocation, before any output:codesign --verify --deep --stricton the installed binary passes, and a byte-for-byte copy of the same file at a different path runs fine — so the binary and its ad-hoc signature are intact. The kill comes from the kernel code-signing subsystem (AMFI), not Gatekeeper (no dialog) or an EDR (none present).Root cause
install_binaryplaces the binary withcp "$binary_path" "$target_path"over an existing target.cponto an existing path isopen(O_TRUNC)+write— it keeps the same inode. When updating in place, the kernel still holds the code-signing validation cached for the previous contents of that vnode; the new pages no longer match →cs_invalid→ AMFI sendsSIGKILLon exec.codesign --verifystill passes because it checks the on-disk seal, not the kernel's cached state.A fresh inode (via
rename()) has no stale cache, which is why copying the file elsewhere makes it run.Fix
Copy to a temporary file next to the target and
mv -fit into place — an atomicrename(), so the new binary always gets a fresh inode. Applied to both the sudo and non-sudo paths.Testing
sh -n tools/install.sh— syntax OK.cpoverwrite; confirmed the installed binary runs after the atomic-replace path.