You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SEA building in a Linux arm64 docker container can corrupt the .gnu.hash section of the binary #61483
Noticed in #59582, I can only reproduce it locally using docker. The Node.js devcontainer image is enough to reproduce this when run on an arm64 host:
docker pull nodejs/devcontainer:nightly
docker run -it nodejs/devcontainer:nightly
In the container:
echo'console.log("hello")'> hello.js
echo'{"main":"./hello.js", "output":"./sea-prep.blob"}'> sea-config.json
node --experimental-sea-config sea-config.json
cp `which node` ./hello
readelf -x .gnu.hash ./hello | head -n 100 # shows the section filled with the symbol lookup table
npx postject hello NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
readelf -x .gnu.hash ./hello | head -n 100 # shows a bunch of zeros
This does not reproduce on a bare-metal Linux arm64 server, or Linux x64 (bare-metal or in docker), which I think is why in the Node.js pull request it only fails in the GitHub action on Linux arm64.
The result of this is that the produced Node.js SEA cannot load any addons using process.dlopen(), because it cannot look up the napi_* symbols from itself (the same can be said about any other non-napi addons, which rely on the same mechanism to look up symbols from the binary to load the addons).
changed the title [-]postject zeros out large chunk of the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]postject zeros corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/+]on Nov 9, 2025
changed the title [-]postject zeros corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]postject corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/+]on Nov 9, 2025
changed the title [-]postject corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]SEA building corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/+]on Jan 23, 2026
changed the title [-]SEA building corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]SEA building in the Linux arm64 docker container can corrupt the .gnu.hash section of the binary[/+]on Jan 23, 2026
changed the title [-]SEA building in the Linux arm64 docker container can corrupt the .gnu.hash section of the binary[/-][+]SEA building in a Linux arm64 docker container can corrupt the .gnu.hash section of the binary[/+]on Jan 23, 2026
[Edited 2026-05-20 — original claim was wrong; replaced with corrected analysis below.]
Apologies — I muddied this thread. After more digging the SIGILL I reported isn't actually downstream of the .gnu.hash corruption you diagnosed. The 5 SIGILLs visible under strace -e signal=all are normal OpenSSL ARM crypto-extension probes (_armv8_sm3_probe, _armv8_sha256_probe, etc.), all caught by OpenSSL's installed SIGILL handler — that's expected on a CPU that doesn't support every extension.
The actual death on my repro is a NULL-deref memcpyafter OpenSSL init completes:
Root cause turned out to be unrelated to your bug: the unofficial-builds linux-arm64-musl binary has all .note* sections stripped and has no PT_NOTE program header at all, so postject's note injection lands in an unreachable section and postject_find_resource() returns NULL. The official node:alpine arm64 has .note.gnu.build-id + a PT_NOTE segment, which is why postject works there.
Filing on unofficial-builds for that. Sorry for the noise on your thread — your .gnu.hash diagnosis is independently real and the per-section diff data still corroborates it for any napi-addon scenario.
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
Activity
joyeecheung commentedon Nov 8, 2025
From:
llvm-readelf-20 --gnu-hash-table ./helloFor comparison, from
llvm-readelf-20 --gnu-hash-table $(which node)It seems postject corrupted the binary with an incorrect size of the bloom filter
[-]postject zeros out large chunk of the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]postject zeros corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/+][-]postject zeros corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]postject corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/+][-]postject corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]SEA building corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/+]joyeecheung commentedon Jan 23, 2026
This is still reproducible even with
--build-seafrom #61167, though hopefully it's now easier to debug without the WASM hoops..[-]SEA building corrupts the .gnu.hash section of the binary in a Linux arm64 docker container[/-][+]SEA building in the Linux arm64 docker container can corrupt the .gnu.hash section of the binary[/+][-]SEA building in the Linux arm64 docker container can corrupt the .gnu.hash section of the binary[/-][+]SEA building in a Linux arm64 docker container can corrupt the .gnu.hash section of the binary[/+]awbx commentedon May 20, 2026
Apologies — I muddied this thread. After more digging the SIGILL I reported isn't actually downstream of the
.gnu.hashcorruption you diagnosed. The 5 SIGILLs visible understrace -e signal=allare normal OpenSSL ARM crypto-extension probes (_armv8_sm3_probe,_armv8_sha256_probe, etc.), all caught by OpenSSL's installed SIGILL handler — that's expected on a CPU that doesn't support every extension.The actual death on my repro is a NULL-deref
memcpyafter OpenSSL init completes:Root cause turned out to be unrelated to your bug: the unofficial-builds
linux-arm64-muslbinary has all.note*sections stripped and has noPT_NOTEprogram header at all, so postject's note injection lands in an unreachable section andpostject_find_resource()returns NULL. The officialnode:alpinearm64 has.note.gnu.build-id+ aPT_NOTEsegment, which is why postject works there.Filing on
unofficial-buildsfor that. Sorry for the noise on your thread — your.gnu.hashdiagnosis is independently real and the per-section diff data still corroborates it for any napi-addon scenario.fix: run postject SEA injection under x64 node for both arches
test: fix Linux debug skip in SEA test guard
test: fix Linux debug skip in SEA test guard
test: fix Linux debug skip in SEA test guard
test: fix Linux debug skip in SEA test guard
github-actions commentedon Sep 3, 2026
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
test: fix Linux debug skip in SEA test guard
test: fix Linux debug skip in SEA test guard
inoway46 commentedon Sep 29, 2026
Still reproduces with postject on Linux arm64 in Docker: reproduction run