Stream: git-wasmtime

Topic: wasmtime / Issue #2273 Restrict memory usage


view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2020 at 19:42):

mleonhard edited Issue #2273:

I wish to use wasmtime in a server to run small untrusted code blocks. I need to limit the maximum memory consumed by each running block to 5MB. I looked through the docs and found no way to restrict how much memory the VM can allocate. There seems to be a built-in limit of 4GB. See #1872 .

Let's support or document how to restrict total instance memory.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2020 at 19:42):

mleonhard edited Issue #2273:

I wish to use wasmtime in a server to run small untrusted code blocks. I need to limit the maximum memory consumed by each running block to 5MB. I looked through the docs and found no way to restrict how much memory the VM can allocate. There seems to be a built-in limit of 4GB. See #1872 .

Let's support or document how to restrict memory usage.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2020 at 19:48):

bjorn3 commented on Issue #2273:

For imported memory you can set the limit when creating the memory. For exported memory you could parse the module and check that the memory limit is at most 5MB.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2020 at 19:57):

alexcrichton commented on Issue #2273:

You can control memory via a number of different means. Application-level configuration happens through the Config type. For example you can use static_memory_maximum_size, static_memory_guard_size, and dynamic_memory_guard_size to tweak how wasmtime allocates memory. The smallest VM reservations will come with a static max size of 0 and a dynamic guard of zero, but code will not perform as well at runtime.

You can further configure the with_host_memory method which means that your application is bringing its own memory allocation strategy, where you can limit even the size of locally defined memories in a wasm module.

And as @bjorn3 mentioned if you're creating the memory itself then you can specify the maximum size at runtime.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2020 at 23:20):

mleonhard commented on Issue #2273:

Thank you both for your quick replies.

Is there a way to use static_memory_maximum_size, static_memory_guard_size, and dynamic_memory_guard_size to restrict the VM from allocating more memory? Could I set the static_memory_guard_size to 4GB - 5MB? I suppose this could work on a platform with a wide-enough memory address space.

To use wasmtime::Config::with_host_memory, I must implement wasmtime::MemoryCreator. The MemoryCreator is configured on the Engine which contains many VMs. InstanceHandle::new calls instance::create_memories calls MemoryCreator::new_memory and does not pass any data about which VM (Store or Instance) the memory is for. How could I use the engine-specific struct to decide if a particular VM has reached its allocation limit?

I looked at how to check the size of memories in a module. I'm not familiar with WASM memories. Are all module-allocated memories exported? Would this work?

  1. Call wasmtime::Module::exports
  2. Iterate through the result and examine ExternType::Memory entries
  3. Error if there is a missing Limits::max value
  4. Sum up the Limits::max values and error if they go over the limit

wasmparser::Parser can parse the Memory entries. There is a shared flag. I suppose shared=true means the memory is exported. So some WASM binaries might have shared=false memories, which would not appear in the list of exports. So I cannot use wasmtime::Module::exports to count total memory usage. wasmparser::Parser should work. I think this might be the solution.

Does WASM define any way for a module to make new Memory objects at runtime?

view this post on Zulip Wasmtime GitHub notifications bot (Oct 06 2020 at 23:28):

mleonhard commented on Issue #2273:

An article that describes how WASM memories work:
https://depth-first.com/articles/2019/10/16/compiling-c-to-webassembly-and-running-it-without-emscripten/

view this post on Zulip Wasmtime GitHub notifications bot (Oct 07 2020 at 01:08):

alexcrichton commented on Issue #2273:

@mleonhard I'd recommend reading the documentation about dynamic/static memories. Unfortunately there is no "disallow more than 5MB per instance" switch in Wasmtime, and this is something that will require work to be done at this time. The MemoryCreator trait allows a custom implementation which you can embed with specifics related to your application. You can track growth and allocation to disallow or arbitrarily "fail" growth beyond a certain point.

For wasm memories in general, I'd recommend reading up on documentation in the wasm spec or in various posts online. Wasm modules can define or import a memory. Memories always state a minimum size and optionally have a maximum size. You would probably want to validate in your application that the minimum size isn't too big.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 11 2020 at 00:24):

mleonhard commented on Issue #2273:

I found the answer: Code in a Wasm VM cannot make new Memory objects. See WebAssembly 1.1 Memories. Every Wasm binary can define exactly one Memory object with a specified initial size and an optional max size. Code inside the VM can use memory instructions to grow a Memory region, up to its max size.

Code in a Wasm VM could import and call a function that makes a new Memory object or does anything. By default, a wasmtime VM does not provide any importable functions to code inside the VM. Call wasmtime_wasi::Wasi::new to make WASI functions importable. See example Embedding in Rust - WASI.

To check the max memory usage of a program running inside a wasmtime VM, parse the binary and check the max size of the single Memory entry.

To set the memory usage limit of a program running inside a wasmtime VM, modify the binary to set the max size value of the Memory entry. The object crate has an API and an example that could be adapted to modify Wasm binaries, but it won't be pretty.

I also found WASM Micro Runtime which provides a simple way to limit memory. But it has no Rust bindings.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 11 2020 at 01:10):

mleonhard commented on Issue #2273:

https://crates.io/crates/parity-wasm looks like a very clean library for modifying Wasm binaries to set memory max size.


Last updated: Oct 23 2024 at 20:03 UTC