SIMD-0219
Stricter ABI and Runtime Constraints
Feature Gate Status
C37iaPi6VE4CZDueU1vL8y6pGp5i8amAbEsF31xzz723
TL;DR
Removing pitfalls and foot-guns from the ABI (including syscalls) and runtime.
Summary
Removing pitfalls and foot-guns from the ABI (including syscalls) and runtime.
Motivation
There are a couple of interactions between dApps and the virtual machine which are currently allowed but make no sense and are even dangerous for dApps: - CPI verification - Allows accidentally using `AccountInfo` structures which the program runtime never serialized - `AccountInfo` structures can be overwritten by CPI during CPI, causing complex side effects - Syscall alignment requirements - In ABI v0 the account input region has no alignment guarantees (it is 1 byte aligned) and ABI v1 has 8 byte alignment. However, there are some syscalls such as the reading of sysvars which require 16 byte alignment. - VM memory access - Bad read accesses to account payload go unnoticed as long as they stay within the reserved address space, even if they leave the actual account payload - Bad write accesses to account payload go unnoticed as long as the original value is restored - Syscall slice parameters - Bad read and write accesses which span nonsensical ranges go unnoticed Furthermore, at the moment all validator implementations have to copy (and compare) data in and out of the virtual memory of the virtual machine. There are four possible account data copy paths: - Serialization: Copy from program runtime (host) to virtual machine (guest) - CPI call edge: Copy from virtual machine (guest) to program runtime (host) - CPI return edge: Copy from program runtime (host) to virtual machine (guest) - Deserialization: Copy from virtual machine (guest) to program runtime (host) By restricting the allowed behavior of dApps we enable the validator to map account payload data directly, avoiding copies and compares.
Key Changes
- Readonly data (0x100000000..0x200000000)
- Stack (0x200000000..0x300000000)
- Heap (0x300000000..0x400000000)
- Instruction meta data
- Account meta data
- Account payload address space
- Instruction payload and program key
- The following pointers must be on the stack or heap,
- The destination address of all sysvar related syscalls
- The pointer in the array of &[AccountInfo] / SolAccountInfo
- The AccountInfo::data field, which is a RefCell<&[u8]> in sol_invoke_signed_rust
- The AccountInfo::lamports field, which is a RefCell<&u64> in sol_invoke_signed_rust
- The following pointers must point to what was originally serialized in the
- AccountInfo::key / SolAccountInfo::key
- AccountInfo::owner / SolAccountInfo::owner
- AccountInfo::lamports / SolAccountInfo::lamports
- AccountInfo::data::ptr / SolAccountInfo::data
- The access is completely within the maximum account length,
- The access is completely within the rest of the account growth budget of the
- The access is completely within the current length of the account,
Impact
These restrictions have been extensively tested by replay against MNB. Most of the dApps devs whose dApps would fail have been contacted and had their dApps fixed already. Programs which used the SDKs account realloc function, which is now deprecated, should upgrade in order to avoid the read-before-write access to uninitialized memory.
Security Considerations
None.