Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions crates/solana_rbpf/RUSTSEC-0000-0000.md
Original file line number Diff line number Diff line change
@@ -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::<MyContext>::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::<u64>()
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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```