diff --git a/benches/elf_loader.rs b/benches/elf_loader.rs index 323be403d..0266b7f74 100644 --- a/benches/elf_loader.rs +++ b/benches/elf_loader.rs @@ -10,6 +10,7 @@ extern crate solana_rbpf; extern crate test; extern crate test_utils; +use solana_rbpf::program::SyscallRegistry; use solana_rbpf::{ elf::Executable, program::{BuiltinFunction, BuiltinProgram, FunctionRegistry}, @@ -27,6 +28,7 @@ fn loader() -> Arc> { Arc::new(BuiltinProgram::new_loader( Config::default(), function_registry, + SyscallRegistry::default(), )) } diff --git a/fuzz/fuzz_targets/dumb.rs b/fuzz/fuzz_targets/dumb.rs index c1b1743d2..c91799e5b 100644 --- a/fuzz/fuzz_targets/dumb.rs +++ b/fuzz/fuzz_targets/dumb.rs @@ -8,7 +8,7 @@ use solana_rbpf::{ ebpf, elf::Executable, memory_region::MemoryRegion, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SyscallRegistry, SBPFVersion}, verifier::{RequisiteVerifier, Verifier}, vm::TestContextObject, }; @@ -29,7 +29,7 @@ fuzz_target!(|data: DumbFuzzData| { let prog = data.prog; let config = data.template.into(); let function_registry = FunctionRegistry::default(); - let syscall_registry = FunctionRegistry::>::default(); + let syscall_registry = SyscallRegistry::>::default(); if RequisiteVerifier::verify(&prog, &config, &SBPFVersion::V2, &function_registry, &syscall_registry).is_err() { // verify please @@ -41,6 +41,7 @@ fuzz_target!(|data: DumbFuzzData| { std::sync::Arc::new(BuiltinProgram::new_loader( config, FunctionRegistry::default(), + syscall_registry, )), SBPFVersion::V2, function_registry, diff --git a/fuzz/fuzz_targets/smart.rs b/fuzz/fuzz_targets/smart.rs index 0ecb535bf..2b8a46f08 100644 --- a/fuzz/fuzz_targets/smart.rs +++ b/fuzz/fuzz_targets/smart.rs @@ -10,7 +10,7 @@ use solana_rbpf::{ elf::Executable, insn_builder::{Arch, IntoBytes}, memory_region::MemoryRegion, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SyscallRegistry, SBPFVersion}, verifier::{RequisiteVerifier, Verifier}, vm::TestContextObject, }; @@ -33,7 +33,7 @@ fuzz_target!(|data: FuzzData| { let prog = make_program(&data.prog, data.arch); let config = data.template.into(); let function_registry = FunctionRegistry::default(); - let syscall_registry = FunctionRegistry::>::default(); + let syscall_registry = SyscallRegistry::>::default(); if RequisiteVerifier::verify( prog.into_bytes(), @@ -53,6 +53,7 @@ fuzz_target!(|data: FuzzData| { std::sync::Arc::new(BuiltinProgram::new_loader( config, FunctionRegistry::default(), + syscall_registry, )), SBPFVersion::V2, function_registry, diff --git a/fuzz/fuzz_targets/smart_jit_diff.rs b/fuzz/fuzz_targets/smart_jit_diff.rs index 87203ca28..b7a7bb50a 100644 --- a/fuzz/fuzz_targets/smart_jit_diff.rs +++ b/fuzz/fuzz_targets/smart_jit_diff.rs @@ -8,7 +8,7 @@ use solana_rbpf::{ elf::Executable, insn_builder::{Arch, Instruction, IntoBytes}, memory_region::MemoryRegion, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SyscallRegistry, SBPFVersion}, verifier::{RequisiteVerifier, Verifier}, vm::TestContextObject, }; @@ -40,7 +40,7 @@ fuzz_target!(|data: FuzzData| { .push(); let config = data.template.into(); let function_registry = FunctionRegistry::default(); - let syscall_registry = FunctionRegistry::>::default(); + let syscall_registry = SyscallRegistry::>::default(); if RequisiteVerifier::verify( prog.into_bytes(), @@ -61,6 +61,7 @@ fuzz_target!(|data: FuzzData| { std::sync::Arc::new(BuiltinProgram::new_loader( config, FunctionRegistry::default(), + syscall_registry, )), SBPFVersion::V2, function_registry, diff --git a/fuzz/fuzz_targets/smarter_jit_diff.rs b/fuzz/fuzz_targets/smarter_jit_diff.rs index 6d77df41f..9a63a39f1 100644 --- a/fuzz/fuzz_targets/smarter_jit_diff.rs +++ b/fuzz/fuzz_targets/smarter_jit_diff.rs @@ -8,7 +8,7 @@ use solana_rbpf::{ elf::Executable, insn_builder::IntoBytes, memory_region::MemoryRegion, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SyscallRegistry, SBPFVersion}, verifier::{RequisiteVerifier, Verifier}, vm::TestContextObject, }; @@ -30,7 +30,7 @@ fuzz_target!(|data: FuzzData| { let prog = make_program(&data.prog); let config = data.template.into(); let function_registry = FunctionRegistry::default(); - let syscall_registry = FunctionRegistry::>::default(); + let syscall_registry = SyscallRegistry::>::default(); if RequisiteVerifier::verify( prog.into_bytes(), @@ -51,6 +51,7 @@ fuzz_target!(|data: FuzzData| { std::sync::Arc::new(BuiltinProgram::new_loader( config, FunctionRegistry::default(), + syscall_registry, )), SBPFVersion::V2, function_registry, diff --git a/fuzz/fuzz_targets/verify_semantic_aware.rs b/fuzz/fuzz_targets/verify_semantic_aware.rs index 0c2cc09f6..9580fbd0e 100644 --- a/fuzz/fuzz_targets/verify_semantic_aware.rs +++ b/fuzz/fuzz_targets/verify_semantic_aware.rs @@ -5,7 +5,7 @@ use libfuzzer_sys::fuzz_target; use semantic_aware::*; use solana_rbpf::{ insn_builder::IntoBytes, - program::{BuiltinFunction, FunctionRegistry, SBPFVersion}, + program::{BuiltinFunction, FunctionRegistry, SyscallRegistry, SBPFVersion}, verifier::{RequisiteVerifier, Verifier}, vm::TestContextObject, }; @@ -25,7 +25,7 @@ fuzz_target!(|data: FuzzData| { let prog = make_program(&data.prog); let config = data.template.into(); let function_registry = FunctionRegistry::default(); - let syscall_registry = FunctionRegistry::>::default(); + let syscall_registry = SyscallRegistry::>::default(); RequisiteVerifier::verify( prog.into_bytes(), diff --git a/src/elf.rs b/src/elf.rs index 1e8a40413..0f1966c05 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -1147,6 +1147,7 @@ pub(crate) fn get_ro_region(ro_section: &Section, elf: &[u8]) -> MemoryRegion { #[cfg(test)] mod test { use super::*; + use crate::program::SyscallRegistry; use crate::{ elf_parser::{ // FIXME consts::{ELFCLASS32, ELFDATA2MSB, ET_REL}, @@ -1163,6 +1164,7 @@ mod test { use rand::{distributions::Uniform, Rng}; use std::{fs::File, io::Read}; use test_utils::assert_error; + type ElfExecutable = Executable; fn loader() -> Arc> { @@ -1177,6 +1179,7 @@ mod test { Arc::new(BuiltinProgram::new_loader( Config::default(), function_registry, + SyscallRegistry::default(), )) } @@ -1932,6 +1935,7 @@ mod test { ..Config::default() }, FunctionRegistry::default(), + SyscallRegistry::default(), ); let elf_bytes = std::fs::read("tests/elfs/syscall_reloc_64_32_sbpfv1.so") .expect("failed to read elf file"); diff --git a/src/program.rs b/src/program.rs index 628f6d389..131b08f56 100644 --- a/src/program.rs +++ b/src/program.rs @@ -228,13 +228,11 @@ impl Default for SyscallRegistry { } } -impl SyscallRegistry { +impl SyscallRegistry { /// Create a new registry based on a previously created vector of registrations. /// We expect the vector to be dense, containing one function per position. pub fn new(registry: Vec<(Vec, T)>) -> Self { - SyscallRegistry { - look_up: registry, - } + SyscallRegistry { look_up: registry } } /// Retrieve a syscall from the registry @@ -243,9 +241,12 @@ impl SyscallRegistry { return Err(ElfError::InvalidSyscallCode); } - self.look_up.get(code-1).as_ref() - .map_or(Err(ElfError::InvalidSyscallCode), - |(name, value)| Ok((name.as_slice(), *value))) + self.look_up + .get(code.saturating_sub(1)) + .as_ref() + .map_or(Err(ElfError::InvalidSyscallCode), |(name, value)| { + Ok((name.as_slice(), *value)) + }) } } @@ -271,7 +272,11 @@ impl PartialEq for BuiltinProgram { impl BuiltinProgram { /// Constructs a loader built-in program - pub fn new_loader(config: Config, functions: FunctionRegistry>, syscalls: SyscallRegistry>) -> Self { + pub fn new_loader( + config: Config, + functions: FunctionRegistry>, + syscalls: SyscallRegistry>, + ) -> Self { Self { config: Some(Box::new(config)), functions, @@ -280,7 +285,10 @@ impl BuiltinProgram { } /// Constructs a built-in program - pub fn new_builtin(functions: FunctionRegistry>, syscalls: SyscallRegistry>) -> Self { + pub fn new_builtin( + functions: FunctionRegistry>, + syscalls: SyscallRegistry>, + ) -> Self { Self { config: None, functions, @@ -421,19 +429,30 @@ mod tests { function_registry_c .register_function_hashed(*b"log_64", syscalls::SyscallU64::vm) .unwrap(); - let builtin_program_a = BuiltinProgram::new_loader(Config::default(), function_registry_a); - let builtin_program_b = BuiltinProgram::new_loader(Config::default(), function_registry_b); + let builtin_program_a = BuiltinProgram::new_loader( + Config::default(), + function_registry_a, + SyscallRegistry::default(), + ); + let builtin_program_b = BuiltinProgram::new_loader( + Config::default(), + function_registry_b, + SyscallRegistry::default(), + ); assert_eq!(builtin_program_a, builtin_program_b); - let builtin_program_c = BuiltinProgram::new_loader(Config::default(), function_registry_c); + let builtin_program_c = BuiltinProgram::new_loader( + Config::default(), + function_registry_c, + SyscallRegistry::default(), + ); assert_ne!(builtin_program_a, builtin_program_c); } #[test] fn test_syscall_registry() { - let registry_vec = vec![ - (b"log".to_vec(), syscalls::SyscallString::vm) - ]; - let registry = SyscallRegistry::new(registry_vec); + let registry_vec: Vec<(Vec, BuiltinFunction)> = + vec![(b"log".to_vec(), syscalls::SyscallString::vm)]; + let registry = SyscallRegistry::>::new(registry_vec); let lookup_result = registry.lookup_syscall(0); assert_eq!(lookup_result.err().unwrap(), ElfError::InvalidSyscallCode); diff --git a/src/verifier.rs b/src/verifier.rs index 99cc19cb4..d0d6c8f07 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -12,13 +12,13 @@ //! Verifies that the bytecode is valid for the given config. +use crate::program::SyscallRegistry; use crate::{ ebpf, program::{BuiltinFunction, FunctionRegistry, SBPFVersion}, vm::{Config, ContextObject}, }; use thiserror::Error; -use crate::program::SyscallRegistry; /// Error definitions #[derive(Debug, Error, Eq, PartialEq)] @@ -214,12 +214,11 @@ fn check_callx_register( fn check_syscall( code: usize, pc: usize, - registry: &SyscallRegistry> + registry: &SyscallRegistry>, ) -> Result<(), VerifierError> { - registry.lookup_syscall(code).map_or( - Err(VerifierError::InvalidFunction(pc)), - |_| Ok(()) - ) + registry + .lookup_syscall(code) + .map_or(Err(VerifierError::InvalidFunction(pc)), |_| Ok(())) } /// Mandatory verifier for solana programs to run on-chain diff --git a/tests/assembler.rs b/tests/assembler.rs index 66df864d9..77ac06183 100644 --- a/tests/assembler.rs +++ b/tests/assembler.rs @@ -8,7 +8,7 @@ extern crate solana_rbpf; extern crate test_utils; -use solana_rbpf::program::{FunctionRegistry, SBPFVersion}; +use solana_rbpf::program::{FunctionRegistry, SBPFVersion, SyscallRegistry}; use solana_rbpf::vm::Config; use solana_rbpf::{assembler::assemble, ebpf, program::BuiltinProgram, vm::TestContextObject}; use std::sync::Arc; @@ -19,7 +19,11 @@ fn asm(src: &str) -> Result, String> { } fn asm_with_config(src: &str, config: Config) -> Result, String> { - let loader = BuiltinProgram::new_loader(config, FunctionRegistry::default()); + let loader = BuiltinProgram::new_loader( + config, + FunctionRegistry::default(), + SyscallRegistry::default(), + ); let executable = assemble::(src, Arc::new(loader))?; let (_program_vm_addr, program) = executable.get_text_bytes(); Ok((0..program.len() / ebpf::INSN_SIZE) @@ -527,6 +531,7 @@ fn test_tcp_sack() { Arc::new(BuiltinProgram::new_loader( config, FunctionRegistry::default(), + SyscallRegistry::default(), )), ) .unwrap(); diff --git a/tests/disassembler.rs b/tests/disassembler.rs index e77d274fe..cfb6d3768 100644 --- a/tests/disassembler.rs +++ b/tests/disassembler.rs @@ -7,7 +7,7 @@ // copied, modified, or distributed except according to those terms. extern crate solana_rbpf; -use solana_rbpf::program::SBPFVersion; +use solana_rbpf::program::{SBPFVersion, SyscallRegistry}; use solana_rbpf::{ assembler::assemble, program::{BuiltinProgram, FunctionRegistry}, @@ -27,7 +27,11 @@ macro_rules! disasm { }}; ($src:expr, $config:expr) => {{ let src = $src; - let loader = BuiltinProgram::new_loader($config, FunctionRegistry::default()); + let loader = BuiltinProgram::new_loader( + $config, + FunctionRegistry::default(), + SyscallRegistry::default(), + ); let executable = assemble::(src, Arc::new(loader)).unwrap(); let analysis = Analysis::from_executable(&executable).unwrap(); let mut reasm = Vec::new(); diff --git a/tests/execution.rs b/tests/execution.rs index d62832e83..f890e9b67 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -1,5 +1,5 @@ #![allow(clippy::arithmetic_side_effects)] -// #![cfg(all(feature = "jit", not(target_os = "windows"), target_arch = "x86_64"))] +#![cfg(all(feature = "jit", not(target_os = "windows"), target_arch = "x86_64"))] // Copyright 2020 Solana Maintainers // // Licensed under the Apache License, Version 2.0 or @@ -15,6 +15,7 @@ extern crate thiserror; use byteorder::{ByteOrder, LittleEndian}; #[cfg(all(not(windows), target_arch = "x86_64"))] use rand::{rngs::SmallRng, RngCore, SeedableRng}; +use solana_rbpf::program::SyscallRegistry; use solana_rbpf::{ assembler::assemble, declare_builtin_function, ebpf, @@ -31,7 +32,6 @@ use std::{fs::File, io::Read, sync::Arc}; use test_utils::{ assert_error, create_vm, PROG_TCP_PORT_80, TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH, }; -use solana_rbpf::program::SyscallRegistry; const INSTRUCTION_METER_BUDGET: u64 = 1024; @@ -2035,6 +2035,10 @@ fn test_stack2() { #[test] fn test_string_stack() { + let config = Config { + enabled_sbpf_versions: SBPFVersion::V1..=SBPFVersion::V1, + ..Config::default() + }; test_interpreter_and_jit_asm!( " mov r1, 0x78636261 @@ -2065,6 +2069,7 @@ fn test_string_stack() { jeq r1, r6, +1 mov r0, 0x0 exit", + config, [], ( "bpf_str_cmp" => syscalls::SyscallStrCmp::vm, @@ -2373,6 +2378,10 @@ fn test_bpf_to_bpf_scratch_registers() { #[test] fn test_syscall_parameter_on_stack() { + let config = Config { + enabled_sbpf_versions: SBPFVersion::V1..=SBPFVersion::V1, + ..Config::default() + }; test_interpreter_and_jit_asm!( " mov64 r1, r10 @@ -2381,6 +2390,7 @@ fn test_syscall_parameter_on_stack() { syscall bpf_syscall_string mov64 r0, 0x0 exit", + config, [], ( "bpf_syscall_string" => syscalls::SyscallString::vm, @@ -2588,12 +2598,17 @@ fn test_err_syscall_string() { #[test] fn test_syscall_string() { + let config = Config { + enabled_sbpf_versions: SBPFVersion::V1..=SBPFVersion::V1, + ..Config::default() + }; test_interpreter_and_jit_asm!( " mov64 r2, 0x5 syscall bpf_syscall_string mov64 r0, 0x0 exit", + config, [72, 101, 108, 108, 111], ( "bpf_syscall_string" => syscalls::SyscallString::vm, @@ -2605,6 +2620,10 @@ fn test_syscall_string() { #[test] fn test_syscall() { + let config = Config { + enabled_sbpf_versions: SBPFVersion::V1..=SBPFVersion::V1, + ..Config::default() + }; test_interpreter_and_jit_asm!( " mov64 r1, 0xAA @@ -2615,6 +2634,7 @@ fn test_syscall() { syscall bpf_syscall_u64 mov64 r0, 0x0 exit", + config, [], ( "bpf_syscall_u64" => syscalls::SyscallU64::vm, @@ -2706,7 +2726,11 @@ declare_builtin_function!( function_registry .register_function_hashed(*b"nested_vm_syscall", SyscallNestedVm::vm) .unwrap(); - let loader = BuiltinProgram::new_loader(Config::default(), function_registry, SyscallRegistry::default()); + let config = Config { + enabled_sbpf_versions: SBPFVersion::V1..=SBPFVersion::V1, + ..Config::default() + }; + let loader = BuiltinProgram::new_loader(config, function_registry, SyscallRegistry::default()); let mem = [depth as u8 - 1, throw as u8]; let mut executable = assemble::( " @@ -3022,6 +3046,10 @@ fn test_far_jumps() { #[test] fn test_symbol_relocation() { + let config = Config { + enabled_sbpf_versions: SBPFVersion::V1..=SBPFVersion::V1, + ..Config::default() + }; test_interpreter_and_jit_asm!( " mov64 r1, r10 @@ -3030,6 +3058,7 @@ fn test_symbol_relocation() { syscall bpf_syscall_string mov64 r0, 0x0 exit", + config, [72, 101, 108, 108, 111], ( "bpf_syscall_string" => syscalls::SyscallString::vm, @@ -4136,7 +4165,11 @@ fn test_invalid_exit_or_return() { ..Config::default() }; let function_registry = FunctionRegistry::>::default(); - let loader = Arc::new(BuiltinProgram::new_loader(config, function_registry, SyscallRegistry::default())); + let loader = Arc::new(BuiltinProgram::new_loader( + config, + function_registry, + SyscallRegistry::default(), + )); let mut executable = Executable::::from_text_bytes( prog, loader, diff --git a/tests/verifier.rs b/tests/verifier.rs index 3229003bc..cabdd60d9 100644 --- a/tests/verifier.rs +++ b/tests/verifier.rs @@ -22,6 +22,7 @@ extern crate solana_rbpf; extern crate thiserror; +use solana_rbpf::program::SyscallRegistry; use solana_rbpf::{ assembler::assemble, ebpf, @@ -34,7 +35,6 @@ use solana_rbpf::{ use std::sync::Arc; use test_utils::{assert_error, create_vm}; use thiserror::Error; -use solana_rbpf::program::SyscallRegistry; /// Error definitions #[derive(Debug, Error)] @@ -329,9 +329,8 @@ fn test_verifier_known_syscall() { 0x95, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // syscall 1 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // return ]; - let syscalls : Vec<(Vec, BuiltinFunction)> = vec![ - (b"my_syscall".to_vec(), syscalls::SyscallString::vm) - ]; + let syscalls: Vec<(Vec, BuiltinFunction)> = + vec![(b"my_syscall".to_vec(), syscalls::SyscallString::vm)]; let syscall_registry = SyscallRegistry::>::new(syscalls); let executable = Executable::::from_text_bytes(