posborne opened PR #15101 from posborne:resource-table-host-heap-limiter to bytecodealliance:main:
Motivation
Embedders currently lack an aggregate host-side memory boundary for component model resources in
ResourceTable. While #12652 added mitigations around handle counts and hostcall fuel, cumulative host heap allocations owned by resources inResourceTablewere previously untracked by any umbrella mechanism.Over the past several releases, Wasmtime has had to address a recurring class of guest-driven host memory exhaustion advisories with mitigations including [GHSA-852m-cvvp-9p4w] and [GHSA-243v-98vx-264h] (#12652), [GHSA-c9gc-w9vx-w86p], [GHSA-gqmc-89g8-p25r], and [GHSA-6fr9-xmw9-5352]. While per-resource and per-call limits help, they do not bound the aggregate host heap memory accumulated across entries in a
ResourceTable.Solution
This PR adds host heap usage accounting and optional per-table byte limits to
wasmtime::component::ResourceTable. This provides a level of umbrella coverage to protect against host paths that may not have protections currently and to provide a higher level limit that is easier to reason about for embedders.The way that this is achieved involves the introduction of a
HostHeapUsagetrait which is required for all resources. This is accompanied by aFixedHostHeapUsagetrait as a marker for types which do not contain children with heap storage not accounted for in their own size directly. Methods on the table that push, delete or mutate (update) resources use the traits to account for the heap usage changes associated with the operation. If a limit is set and an operation causes the heap usage to grow beyond the set limit, the operations return an error which will typically result in a guest-side trap.These new requirements necessitate updates across the wasmtime tree and will be a breaking change for embedders that are pushing their own resources into
ResourceTables.Design Decisions
The code here has gone through a few iterations and updates based on discussion in #12984. What is present here tries to incorporate that feedback and is closer to some of the implementation from servo/firefox/stylo
MallocSizeOftrait.In instrumenting the code to implement the traits, I decided that to ease the burden on embedders and to provide some additional static guarantees, it would be beneficial to introduce proc-macros in order to aid in deriving the traits on compatible structs and enums.
For mutation I went with a closure-based
updaterather than a guard, because the limit check has to be fallible and a guard could only account inDrop. This makes former get_mut call sites a bit noisier. Since update can only measure after the mutation runs, growth past the limit is reported rather than prevented, and the mutation isn't rolled back because the error is expected to trap. The overshoot is roughly limited to what a single host call can allocate.Across the code in tree (mostly wasi p2/p3), I tried to provide pragmatic implementations of the trait where reasonable and erred on the side of overcounting bytes in most cases. There are some reference counted cases which are not tracked with complete accuracy but, even in those cases, abuse should be challenging as the fixed size of the resource will be counted even if the amortized cost of the shared data is left unaccounted.
Future Work
The changes here are sprawling, so I wanted to avoid increasing the scope beyond what was required for purpose and reasonable ergonomics (adding derive). Potential future work that I opted to not try to incorporate here include:
- Allow for the limit to be set at a higher level outside of individual tables, probably on the
ResourceLimiter.- Hooks to intervene when limits are exceeded or at watermarks prior to the limit.
- Fast path or conditional compilation to opt out of tracking; even if no limit is set the accounting is done and count is available.
Closes #12984
[GHSA-852m-cvvp-9p4w]: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-852m-cvvp-9p4w
[GHSA-243v-98vx-264h]: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-243v-98vx-264h
[GHSA-c9gc-w9vx-w86p]: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-c9gc-w9vx-w86p
[GHSA-gqmc-89g8-p25r]: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-gqmc-89g8-p25r
[GHSA-6fr9-xmw9-5352]: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-6fr9-xmw9-5352
posborne removed the review request for wasmtime-wasi-reviewers from PR #15101.
posborne requested rvolosatovs for a review on PR #15101.
posborne requested wasmtime-wasi-reviewers for a review on PR #15101.
posborne removed the review request for wasmtime-core-reviewers from PR #15101.
posborne requested alexcrichton for a review on PR #15101.
posborne requested wasmtime-core-reviewers for a review on PR #15101.
github-actions[bot] added the label wasi on PR #15101.
github-actions[bot] added the label wasmtime:c-api on PR #15101.
Last updated: Oct 31 2026 at 23:03 UTC