Flow: Linking of guest code
The processing of guest imports starts before the virtual machine is instantiated at the validation and instrumentation stage, implemented within ScryptoV1WasmValidator::validate
.
Once the module itself is statically validated, instrumented, and rewritten, the next step of validation is handed over to the specific VM implementation where the functions are instantiated, currently WasmerModule::instantiate
and WasmiModule::host_funcs_set
.
The linkage process is security sensitive as if the guest module is able to corrupt its own metadata (e.g., WASM spec is not followed and the guest code can export its own imports allowing the module to overwrite its own imports), it would enable DOS attacks. This is due to the fact that costing is handled via a callout to the env.gas
function from the guest code, inserted at the time of instrumentation, which if corrupted, would lead to the execution-costing mechanism being bypassed.
Function: WasmModule::enforce_import_constraints
This is the method that validates the imports of the guest code,
which enforces the following constraints: 1) the imported function is valid for the given module and the version of the runtime it is linking against and 2) the type signature of the target function matches the imported function.
It achieves this by iterating over the imports of the module and switching on the import name:
Function: WasmiModule::host_funcs_set
This method finalizes the instantiation of the guest module by setting up the host functions that the guest module can call. It does so by instantiating each host function and then adding it to the linker. The WASMI linker then provides the appropriate bindings to invoke.
Switch statements
The switch statements in the enforce_import_constraints
and host_funcs_set
methods are a potential source of error as they are rather large and maintained by hand.
It is worth noting that a bug within these statements would most likely be caught by the comprehensive integration tests, but it remains a potential area for improvement as a proc macro could be used at the function-definition level to generate both the import validation and the runtime-specific bindings, eliminating the need for maintenance for both switch statements.