sdk: reserve an 8 MiB main-thread shadow stack for linked programs - #842
sdk: reserve an 8 MiB main-thread shadow stack for linked programs#842brandonpayton wants to merge 2 commits into
Conversation
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| icu | wasm32 | built | 297a2f0c |
| libcurl | wasm32 | built | 47b2440d |
| libcxx | wasm32 | built | c6cce11e |
| libcxx | wasm64 | built | 1407cb4b |
| libiconv | wasm32 | built | 86049231 |
| libpng | wasm32 | built | cffa4555 |
| libxml2 | wasm32 | built | 2a413334 |
| libzip | wasm32 | built | 6521d0d2 |
| openssl | wasm32 | built | d3cb845b |
| openssl | wasm64 | built | 044b1b8c |
| sqlite | wasm32 | built | ba7f72f5 |
| sqlite | wasm64 | built | 0c343dd8 |
| zlib | wasm32 | built | 4f716fce |
| zlib | wasm64 | built | b5de4194 |
| bc | wasm32 | built | b9fe6182 |
| bzip2 | wasm32 | built | 5bb39152 |
| coreutils | wasm32 | built | 6dd28e2c |
| curl | wasm32 | built | 982dd0cc |
| dash | wasm32 | built | 7ec1a402 |
| diffutils | wasm32 | built | fb7449d7 |
| dinit | wasm32 | built | 7863be5d |
| fbdoom | wasm32 | built | c1deba45 |
| file | wasm32 | built | f6e0d0e7 |
| findutils | wasm32 | built | 97692b4a |
| gawk | wasm32 | built | e57e8cf8 |
| git | wasm32 | built | 997a3170 |
| grep | wasm32 | built | be691a28 |
| gzip | wasm32 | built | ab013af5 |
| hello | wasm32 | built | fc9eb295 |
| kandelo-sdk | wasm32 | built | 95370058 |
| kernel | wasm32 | built | d2b8f035 |
| less | wasm32 | built | d5cbbf8b |
| lsof | wasm32 | built | 7f55101c |
| m4 | wasm32 | built | 5b0cae14 |
| make | wasm32 | built | 281b19d7 |
| mariadb | wasm32 | built | 5813cfca |
| mariadb | wasm64 | built | 295e8dff |
| modeset | wasm32 | built | ee391a0a |
| msmtpd | wasm32 | built | 11ce4a72 |
| nano | wasm32 | built | af164b1f |
| ncurses | wasm32 | built | 0cd7f951 |
| netcat | wasm32 | built | 1c419f24 |
| nginx | wasm32 | built | 684016cd |
| php | wasm32 | built | d1b310cf |
| posix-utils-lite | wasm32 | built | 7909e25d |
| ruby | wasm32 | built | 9bc6deab |
| sed | wasm32 | built | 61ffc7ee |
| spidermonkey | wasm32 | built | 9664571c |
| tar | wasm32 | built | 2f3a42cc |
| tcl | wasm32 | built | 36656326 |
| unzip | wasm32 | built | 912c5251 |
| userspace | wasm32 | built | 0b8c637e |
| vim | wasm32 | built | e0218a9b |
| wget | wasm32 | built | 6ac5c9d9 |
| xz | wasm32 | built | 79ade065 |
| zip | wasm32 | built | 0d88dadb |
| zstd | wasm32 | built | 3fb34310 |
| bash | wasm32 | built | 35d15ecf |
| mariadb-test | wasm32 | built | 4bbce5c4 |
| mariadb-vfs | wasm32 | built | cc7c3a93 |
| mariadb-vfs | wasm64 | built | 4dffb637 |
| nethack | wasm32 | built | 43da0b72 |
| node | wasm32 | built | 734d6390 |
| spidermonkey-node | wasm32 | built | 54bba4a1 |
| vim-browser-bundle | wasm32 | built | f018db55 |
| nethack-browser-bundle | wasm32 | built | 1ac8b0d1 |
| rootfs | wasm32 | built | 78f431ee |
| shell | wasm32 | built | a6fc5295 |
| lamp | wasm32 | built | 3c76784e |
| node-vfs | wasm32 | built | 81978a15 |
| wordpress | wasm32 | built | ae3a8ba0 |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
cdff91f to
2dc2115
Compare
Keep parser classifications for SDK mode and thread inference, but forward non-SDK arguments in their original sequence so objects, -l libraries, archives, and linker group controls retain normal static-link semantics. Add unit and real wasm-ld coverage for mixed input ordering and linker controls.
2dc2115 to
39f72a3
Compare
39f72a3 to
b3584f0
Compare
|
Exact-head review after the push found one additional linker-trace path bug, so this PR is draft again and With The correction will derive the effective working directory from Clang's actual quote-aware |
WebAssembly has no shadow-stack guard page. wasm-ld's roughly 64 KiB default lets deep ordinary call chains overwrite adjacent .bss state, including Kandelo's pthread and TLS globals, before failing later in unrelated code. Reserve 8 MiB, matching the common Linux main-thread default, while preserving any valid larger stack requested by the caller. For Node-hosted commands, first ask the pinned Clang or Clang++ driver for its real -### job graph without injecting SDK glue. Compiler-only modes such as -fsyntax-only, -M, -MM, and --analyze then bypass executable preparation even when they arrive through response files. Confirmed executable links get a second trace with the complete SDK inputs; exactly one pinned wasm-ld job is required, while the wrapped toolchain's expected wasm-opt post-link job remains valid. The Kandelo-native driver applies the same job-graph classification before its direct-link path. Compute the effective stack floor from the exact pinned wasm-ld argv. Relative lld responses use the source-proven driver working-directory slot in LLVM 21's cc1 command. Response expansion is iterative rather than depth-limited: both drivers reject missing files, active canonical cycles, or explicit file/token/text resource limits before linking, and inspect 100-level LLVM-accepted chains without silently lowering a larger request. The Node path decodes LLVM-compatible UTF-8 and BOM-marked UTF-16; the Kandelo-native driver rejects UTF-16 explicitly because Bash cannot retain embedded NUL bytes and the packaged SDK declares no transcoder. Cover both drivers with parser, malformed-input, response-file, fail-closed trace, and real LLVM tests. Direct and response-file forms of all four compiler-only modes run through the actual Node and Kandelo-native entrypoints, with their outputs confined to temporary directories. Executable coverage includes interleaved optimization, include-path, PCH, framework, working-directory, deep-chain, cycle, and alias-cycle cases. The Node path pays for two non-compiling Clang traces per executable link and one for an otherwise-unrecognized compiler-only mode; the native path pays for one classification trace before a possible link. No ABI bump is required because this changes user-program link layout only; the host reads each module's exported stack and heap positions dynamically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b3584f0 to
457188e
Compare
|
Absorbed by rebase-merged #967. Main is now 6efb411 with the sealed tree b133bfa018f7e2bc84c4845edf2f945b2f844954, and ABI 41 activation completed successfully in run 29550069085. The absorption audit confirmed this PR\x27s behavior and tests are present in that merged tree, so this source PR is closed and its branch is deleted. |
Why
WebAssembly programs use a shadow stack in linear memory for ordinary C and C++ function calls. If that stack is too small, calls can overwrite unrelated allocator and thread-local-storage data before the runtime notices a failure. wasm-ld is the linker that lays out this memory.
Prevent ordinary deep C/C++ call chains from silently overflowing wasm-ld's roughly 64 KiB default main-thread shadow stack into Kandelo's allocator and pthread/TLS globals.
This is an SDK memory-layout defect, not a package compatibility workaround. It was reproduced by ncurses terminfo loading and GTK image loading, where the eventual trap occurred far from the actual stack overwrite.
What changed
A response file is a text file whose arguments are expanded by the compiler or linker. Because callers can put stack-size options inside nested response files, both SDK drivers must inspect them before enforcing the safe minimum.
-###job graph before changing executable links. Compiler-only modes remain compiler-only; executable links require exactly one pinned wasm-ld job.POSIX leaves the default stack size implementation-defined. 8 MiB matches the common Linux/glibc main-thread default. This affects only the initial thread; pthread stacks continue to use musl's separate default.
Compatibility
Valid compiler-only actions remain intact in both drivers, including direct and response-file forms of:
-fsyntax-only-M-MM--analyzeResponse expansion is bounded at 4,096 files, 1,048,576 tokens, and 64 MiB of decoded text. Exceeding a bound fails explicitly before output instead of risking a silently lowered stack request.
ABI
No ABI change. The host discovers each module's exported
__heap_baseand__stack_pointerdynamically. Existing binaries and newly linked 8 MiB binaries remain compatible with the same kernel, and the ABI snapshot is unchanged.Exact validation
Exact candidate:
457188e2e065eb70d6cf73b41987c5e90cf12f15Tree:
d777e3867d78129b58a08b4dff2331ab117799e0Parent: #913 head
c6849bde6cfbe51837227789840ecf2b05791070-zoperand boundaries preserved a 32 MiB request in both drivers.-ffile-compilation-dir, late-Xclangspoofing, object-only links, and filenames containing newlines were covered.git diff --checkpassed.Merge order
This PR is stacked directly on #913. Merge #913 first, then retarget this one-commit PR to
main.This is a main-repository PR for review and must not be auto-merged.