A few days ago the lWasmtime 6.0.1, 5.0.1 and 4.0.1 corrective updates released which they get to fix a vulnerability (already cataloged under CVE-2023-26489) which was rated critical.
Vulnerability allows to organize the writing of data in a memory area outside the allowed limits for isolated WebAssembly code, which can potentially be used by an attacker to orchestrate execution of their code outside of the isolated WASI environment.
For those unfamiliar with Wasmtime, you should know that this is a runtime for running WebAssembly applications with WASI (WebAssembly System Interface) extensions as normal standalone applications.
Wasmtime is written in Rust and the vulnerability is due to a logical error in the definition of routing rules of linear memory in the Cranelift code generator, which translates an intermediate representation independent of hardware architectures into executable machine code for the x86_64 architecture.
Regarding the fixed vulnerability, it is mentioned that in particular, effective 35-bit addresses were calculated for WebAssembly applications instead of the 33-bit addresses allowed in WebAssembly, which changed the virtual memory limit allowed for read and write operations to 34 GB, while the sandbox environment setting provides protection for 6 GB. from the base address.
Wasmtime's code generator, Cranelift, has a bug in x86_64 targets where the address mode calculation would mistakenly calculate a 35-bit effective address instead of the 33-bit effective address defined by WebAssembly. This bug means that, with the default code generation configuration, a wasm-controlled load/store operation could read/write addresses up to 35 bits away from the base of linear memory.
As a result, the virtual memory range from 6 to 34 GB from the base address became available for reading and writing from WebAssembly applications. This memory can hold other WebAssembly environments or WebAssembly runtime components.
For example (i32.load (i32.shl (local.get 0) (i32.const 3))), is loaded from WebAssembly address $local0 << 3. When translated to Cranelift, the calculation of $local0 << 3 to a 32-bit value, is zero-expanded to a 64-bit value, and then added to the base address of linear memory. Cranelift would generate a statement of the form movl(%base, %local0, 8), %dst which computes %base + %local0 << 3.
The error here, however, is that the address calculation occurs with 64-bit values, where $local0 << 3 was supposed to truncate the address to a 32-bit value. This means that %local0, which can use up to 32 bits for an address, gets an additional 3 bits of address space to be accessible via movl .
Finally, as always it is recommended to update the package to the latest version availableIt is also worth mentioning that there are several possible solutions that can be used to mitigate this problem if the update is not possible.
It is mentioned that none of these solutions are on by default and require explicit configuration:
- If it is not possible to update the version of Wasmtime, the option "Config::static_memory_maximum_size(0)" is mentioned to enable mandatory separate bounds checking on any linear memory access as a workaround to block the error (results in a significant performance degradation).
- Another option is to use the "Config::static_memory_guard_size(1 < 36)" setting to increase the number of guard pages (Guard Page, throw exception when accessed) located in the problematic virtual memory range (leads to reserve a large amount of virtual memory and limiting the number of concurrent WebAssembly applications).
- If it is possible to use a non-x86_64 host, that will also fix this error. This bug does not affect the AArch64 backend of Wasmtime or Cranelift, for example.
Finally If you are interested in knowing more about it, you can check the details in the following link.
Be the first to comment