diff --git a/crates/solana_rbpf/RUSTSEC-0000-0000.md b/crates/solana_rbpf/RUSTSEC-0000-0000.md new file mode 100644 index 000000000..0a9f26281 --- /dev/null +++ b/crates/solana_rbpf/RUSTSEC-0000-0000.md @@ -0,0 +1,104 @@ +```toml +[advisory] +id = "RUSTSEC-0000-0000" +package = "solana_rbpf" +date = "2026-05-28" +url = "https://github.com/solana-labs/rbpf" +informational = "unsound" +categories = ["memory-corruption"] +keywords = ["soundness", "pointer-arithmetic", "out-of-bounds"] + +[affected.functions] +"solana_rbpf::vm::EbpfVm::invoke_function" = [">= 0.8.0, <= 0.8.5"] + +[versions] +patched = [] +unaffected = ["< 0.8.0"] +``` + +# `EbpfVm::invoke_function` performs out-of-bounds pointer arithmetic + +Affected versions of `solana_rbpf` expose the safe method +`EbpfVm::invoke_function`. This method computes an obfuscated VM pointer by +casting `self` to `*mut u64` and applying a randomized offset derived from +`get_runtime_environment_key()`. + +The resulting pointer arithmetic is performed with `ptr::offset`, which +requires the computed pointer to remain within the same allocation. In practice, +the randomized offset can move the pointer far outside the allocation +containing the `EbpfVm`, causing undefined behavior before the supplied builtin +function is invoked. + +The upstream repository is archived, and no patched version is currently +available. + +## Example + +The following safe Rust program triggers undefined behavior in +`EbpfVm::invoke_function`: + +```rust +use solana_rbpf::memory_region::MemoryMapping; +use solana_rbpf::program::{BuiltinProgram, SBPFVersion}; +use solana_rbpf::vm::{Config, ContextObject, EbpfVm}; +use std::sync::Arc; + +struct MyContext; + +impl ContextObject for MyContext { + fn trace(&mut self, _: [u64; 12]) {} + fn consume(&mut self, _: u64) {} + fn get_remaining(&self) -> u64 { + 100000 + } +} + +fn no_op_builtin( + _vm: *mut EbpfVm<'_, MyContext>, + _arg1: u64, + _arg2: u64, + _arg3: u64, + _arg4: u64, + _arg5: u64, +) { +} + +fn main() { + let mut context = MyContext; + let loader = Arc::new(BuiltinProgram::::new_mock()); + let config = Config::default(); + let memory_mapping = MemoryMapping::new(vec![], &config, &SBPFVersion::V1).unwrap(); + + let mut vm = EbpfVm::new( + loader, + &SBPFVersion::V1, + &mut context, + memory_mapping, + 1024, + ); + + vm.invoke_function(no_op_builtin); +} +``` + +## Miri output + +Miri reports out-of-bounds pointer arithmetic inside `invoke_function`: + +```text +error: Undefined Behavior: in-bounds pointer arithmetic failed: +attempting to offset pointer by 337375224 bytes, but got alloc1538 which is only 432 bytes from the end of the allocation + --> solana_rbpf-0.8.5/src/vm.rs:437:17 + | +437 | / std::ptr::addr_of_mut!(*self) +438 | | .cast::() +439 | | .offset(get_runtime_environment_key() as isize) + | |___________________________________________________________________^ Undefined Behavior occurred here + | + = note: inside `solana_rbpf::vm::EbpfVm::<'_, MyContext>::invoke_function` +note: inside `main` + --> src/main.rs:43:5 + | +43 | vm.invoke_function(no_op_builtin); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +```