brintos

brintos / linux public Read only

0
0

binfmt_wasm cannot exec large binaries: 16 MiB exec-staging slot + 64 MiB WASM_MAX_MODULE_SIZE (copy-whole-image model) — blocks self-hosted clang #15

Open sasha opened this issue · 0 comments
S sasha commented

Summary

The binfmt_wasm exec loader copies the WHOLE binary into a contiguous reserved RAM staging slot before instantiation. The slot and the module-size parser cap are sized for small (10 MB) unix utilities, so a large binary — e.g. the self-hosted clang.wasm (588 MB; this bites any hundreds-of-MB program) — is refused with EFBIG.

Symptoms

binfmt_wasm: /init is 587969183 bytes, over the 16777216-byte exec-image staging ceiling
             (strip debug info or grow the setup.c staging reservation)
wasm32: requested init /init failed (error -27 EFBIG)
  • exec-staging slot = exec_stage_sz / WASM32_EXEC_STAGE_SLOTS = 32 MiB / 2 = 16 MiB per exec (setup.c).
  • parser cap WASM_MAX_MODULE_SIZE = 64 MiB (wasm_module.c) rejects even if staging is grown.

Reproducible with ANY wasm binary > 16 MiB exec'd as /init (no special artifact needed) — it is a pure size check, i_size > wasm32_exec_image_max(), visible directly in the code.

Validation workaround (bump the constants — NOT a real fix; let us run the 588 MB clang past staging+parse)

- const unsigned long exec_stage_sz = 32ul * 1024 * 1024;     // arch/wasm32/kernel/setup.c
+ const unsigned long exec_stage_sz = 1280ul * 1024 * 1024;   // 2 slots x 640 MiB
- #define WASM_MAX_MODULE_SIZE  (64u << 20)                    // arch/wasm32/kernel/wasm_module.c
+ #define WASM_MAX_MODULE_SIZE  (1024u << 20)

(To then instantiate the kernel with enough RAM you also need vmlinux --max-memory raised — scripts/link-vmlinux.sh: --max-memory=1073741824 -> 3221225472 — and KERNEL_MIB set to fit the slot.)

Why it's not the real fix

The staging is a permanent contiguous RAM carve-out (600 MB+ for clang) reserved via memblock at boot, on a wasm32 kernel capped at 4 GiB — a lot of RAM committed just to stage one exec image. The loader's own comment already points at the answer: "a bigger reserved slot toward the 64 MiB parser cap would want a streaming loader." The proper fix is a streaming/mmap exec loader that reads the image incrementally into the instance's memory instead of copying the whole binary into a reserved slot first.

Proposed fix targets brintos/linux only — no distro submodule pins moved. All distros share one lineage, so pin bumps are coordinated on merge, not per-engineer.