Skip to content

Commit

Permalink
Verifier is not optional (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackcmay authored Jun 6, 2022
1 parent 2dd2d98 commit 37600ee
Show file tree
Hide file tree
Showing 25 changed files with 613 additions and 440 deletions.
3 changes: 0 additions & 3 deletions benches/elf_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ fn bench_load_elf(bencher: &mut Bencher) {
bencher.iter(|| {
Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
syscall_registry(),
)
Expand All @@ -55,7 +54,6 @@ fn bench_load_elf_without_syscall(bencher: &mut Bencher) {
bencher.iter(|| {
let executable = Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
syscall_registry(),
)
Expand All @@ -72,7 +70,6 @@ fn bench_load_elf_with_syscall(bencher: &mut Bencher) {
bencher.iter(|| {
let executable = Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
syscall_registry(),
)
Expand Down
25 changes: 15 additions & 10 deletions benches/jit_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ extern crate test;
use solana_rbpf::{
elf::Executable,
user_error::UserError,
vm::{Config, EbpfVm, SyscallRegistry, TestInstructionMeter},
vm::{Config, EbpfVm, SyscallRegistry, TestInstructionMeter, VerifiedExecutable},
};
use std::{fs::File, io::Read};
use test::Bencher;
use test_utils::TautologyVerifier;

#[bench]
fn bench_init_vm(bencher: &mut Bencher) {
Expand All @@ -24,14 +25,16 @@ fn bench_init_vm(bencher: &mut Bencher) {
file.read_to_end(&mut elf).unwrap();
let executable = Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
SyscallRegistry::default(),
)
.unwrap();
bencher.iter(|| {
EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], Vec::new()).unwrap()
});
let verified_executable =
VerifiedExecutable::<TautologyVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
bencher.iter(|| EbpfVm::new(&verified_executable, &mut [], Vec::new()).unwrap());
}

#[cfg(not(windows))]
Expand All @@ -40,14 +43,16 @@ fn bench_jit_compile(bencher: &mut Bencher) {
let mut file = File::open("tests/elfs/pass_stack_reference.so").unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_elf(
let executable = Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
SyscallRegistry::default(),
)
.unwrap();
bencher.iter(|| {
Executable::<UserError, TestInstructionMeter>::jit_compile(&mut executable).unwrap()
});
let mut verified_executable =
VerifiedExecutable::<TautologyVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
bencher.iter(|| verified_executable.jit_compile().unwrap());
}
37 changes: 24 additions & 13 deletions benches/vm_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ use solana_rbpf::{
elf::Executable,
memory_region::MemoryRegion,
user_error::UserError,
vm::{Config, EbpfVm, SyscallRegistry, TestInstructionMeter},
vm::{Config, EbpfVm, SyscallRegistry, TestInstructionMeter, VerifiedExecutable},
};
use std::{fs::File, io::Read};
use test::Bencher;
use test_utils::TautologyVerifier;

#[bench]
fn bench_init_interpreter_execution(bencher: &mut Bencher) {
Expand All @@ -26,13 +27,16 @@ fn bench_init_interpreter_execution(bencher: &mut Bencher) {
file.read_to_end(&mut elf).unwrap();
let executable = Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
SyscallRegistry::default(),
)
.unwrap();
let mut vm =
EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], Vec::new()).unwrap();
let verified_executable =
VerifiedExecutable::<TautologyVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
let mut vm = EbpfVm::new(&verified_executable, &mut [], Vec::new()).unwrap();
bencher.iter(|| {
vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: 29 })
.unwrap()
Expand All @@ -45,16 +49,19 @@ fn bench_init_jit_execution(bencher: &mut Bencher) {
let mut file = File::open("tests/elfs/pass_stack_reference.so").unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_elf(
let executable = Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
SyscallRegistry::default(),
)
.unwrap();
Executable::<UserError, TestInstructionMeter>::jit_compile(&mut executable).unwrap();
let mut vm =
EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], Vec::new()).unwrap();
let mut verified_executable =
VerifiedExecutable::<TautologyVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
verified_executable.jit_compile().unwrap();
let mut vm = EbpfVm::new(&verified_executable, &mut [], Vec::new()).unwrap();
bencher.iter(|| {
vm.execute_program_jit(&mut TestInstructionMeter { remaining: 29 })
.unwrap()
Expand All @@ -69,16 +76,20 @@ fn bench_jit_vs_interpreter(
instruction_meter: u64,
mem: &mut [u8],
) {
let mut executable = solana_rbpf::assembler::assemble::<UserError, TestInstructionMeter>(
let executable = solana_rbpf::assembler::assemble::<UserError, TestInstructionMeter>(
assembly,
None,
config,
SyscallRegistry::default(),
)
.unwrap();
Executable::<UserError, TestInstructionMeter>::jit_compile(&mut executable).unwrap();
let mut verified_executable =
VerifiedExecutable::<TautologyVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
verified_executable.jit_compile().unwrap();
let mem_region = MemoryRegion::new_writable(mem, ebpf::MM_INPUT_START);
let mut vm = EbpfVm::new(&executable, &mut [], vec![mem_region]).unwrap();
let mut vm = EbpfVm::new(&verified_executable, &mut [], vec![mem_region]).unwrap();
let interpreter_summary = bencher
.bench(|bencher| {
bencher.iter(|| {
Expand Down
43 changes: 17 additions & 26 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ use solana_rbpf::{
static_analysis::Analysis,
syscalls::Result,
user_error::UserError,
verifier::check,
vm::{Config, DynamicAnalysis, EbpfVm, SyscallObject, SyscallRegistry, TestInstructionMeter},
verifier::RequisiteVerifier,
vm::{
Config, DynamicAnalysis, EbpfVm, SyscallObject, SyscallRegistry, TestInstructionMeter,
VerifiedExecutable,
},
};
use std::{fs::File, io::Read, path::Path};

Expand Down Expand Up @@ -106,34 +109,21 @@ fn main() {
.short('p')
.long("prof"),
)
.arg(
Arg::new("verify")
.about("Run the verifier before execution or disassembly")
.short('v')
.long("veri"),
)
.get_matches();

let config = Config {
enable_instruction_tracing: matches.is_present("trace") || matches.is_present("profile"),
enable_symbol_and_section_labels: true,
..Config::default()
};
let verifier: Option<for<'r> fn(&'r [u8], &Config) -> std::result::Result<_, _>> =
if matches.is_present("verify") {
Some(check)
} else {
None
};
let syscall_registry = SyscallRegistry::default();
let mut executable = match matches.value_of("assembler") {
let executable = match matches.value_of("assembler") {
Some(asm_file_name) => {
let mut file = File::open(&Path::new(asm_file_name)).unwrap();
let mut source = Vec::new();
file.read_to_end(&mut source).unwrap();
assemble::<UserError, TestInstructionMeter>(
std::str::from_utf8(source.as_slice()).unwrap(),
verifier,
config,
syscall_registry,
)
Expand All @@ -142,17 +132,18 @@ fn main() {
let mut file = File::open(&Path::new(matches.value_of("elf").unwrap())).unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
Executable::<UserError, TestInstructionMeter>::from_elf(
&elf,
verifier,
config,
syscall_registry,
)
.map_err(|err| format!("Executable constructor failed: {:?}", err))
Executable::<UserError, TestInstructionMeter>::from_elf(&elf, config, syscall_registry)
.map_err(|err| format!("Executable constructor failed: {:?}", err))
}
}
.unwrap();

let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();

let mut mem = match matches.value_of("input").unwrap().parse::<usize>() {
Ok(allocate) => vec![0u8; allocate],
Err(_) => {
Expand All @@ -178,17 +169,17 @@ fn main() {
.unwrap()
];
if matches.value_of("use") == Some("jit") {
Executable::<UserError, TestInstructionMeter>::jit_compile(&mut executable).unwrap();
verified_executable.jit_compile().unwrap();
}
let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START);
let mut vm = EbpfVm::new(&executable, &mut heap, vec![mem_region]).unwrap();
let mut vm = EbpfVm::new(&verified_executable, &mut heap, vec![mem_region]).unwrap();

let analysis = if matches.value_of("use") == Some("cfg")
|| matches.value_of("use") == Some("disassembler")
|| matches.is_present("trace")
|| matches.is_present("profile")
{
Some(Analysis::from_executable(&executable).unwrap())
Some(Analysis::from_executable(verified_executable.get_executable()).unwrap())
} else {
None
};
Expand Down
2 changes: 0 additions & 2 deletions examples/disassemble.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use solana_rbpf::{
elf::Executable,
static_analysis::Analysis,
user_error::UserError,
verifier::check,
vm::{Config, SyscallRegistry, TestInstructionMeter},
};
use std::collections::BTreeMap;
Expand All @@ -34,7 +33,6 @@ fn main() {
];
let executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(
&program,
Some(check),
Config::default(),
SyscallRegistry::default(),
BTreeMap::default(),
Expand Down
2 changes: 0 additions & 2 deletions examples/to_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use solana_rbpf::{
elf::Executable,
static_analysis::Analysis,
user_error::UserError,
verifier::check,
vm::{Config, SyscallRegistry, TestInstructionMeter},
};
use std::collections::BTreeMap;
Expand All @@ -32,7 +31,6 @@ use std::collections::BTreeMap;
fn to_json(program: &[u8]) -> String {
let executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(
&program,
Some(check),
Config::default(),
SyscallRegistry::default(),
BTreeMap::default(),
Expand Down
9 changes: 9 additions & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ arbitrary = { version = "1.0", features = ["derive"] }
libfuzzer-sys = "0.4"
num-traits = "0.2"
rayon = "1.5"
test_utils = { path = "../test_utils/" }

[dependencies.solana_rbpf]
path = ".."
Expand Down
16 changes: 10 additions & 6 deletions fuzz/fuzz_targets/dumb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ use solana_rbpf::{
elf::{register_bpf_function, Executable},
memory_region::MemoryRegion,
user_error::UserError,
verifier::check,
vm::{EbpfVm, SyscallRegistry, TestInstructionMeter},
verifier::{RequisiteVerifier, Verifier},
vm::{EbpfVm, SyscallRegistry, TestInstructionMeter, VerifiedExecutable},
};
use test_utils::TautologyVerifier;

use crate::common::ConfigTemplate;

Expand All @@ -29,7 +30,7 @@ struct DumbFuzzData {
fuzz_target!(|data: DumbFuzzData| {
let prog = data.prog;
let config = data.template.into();
if check(&prog, &config).is_err() {
if RequisiteVerifier::verify(&prog, &config).is_err() {
// verify please
return;
}
Expand All @@ -39,15 +40,18 @@ fuzz_target!(|data: DumbFuzzData| {
register_bpf_function(&config, &mut bpf_functions, &registry, 0, "entrypoint").unwrap();
let executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(
&prog,
None,
config,
SyscallRegistry::default(),
bpf_functions,
)
.unwrap();
let verified_executable =
VerifiedExecutable::<TautologyVerifier, UserError, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START);
let mut vm =
EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], vec![mem_region]).unwrap();
let mut vm = EbpfVm::new(&verified_executable, &mut [], vec![mem_region]).unwrap();

drop(black_box(vm.execute_program_interpreted(
&mut TestInstructionMeter { remaining: 1024 },
Expand Down
Loading

0 comments on commit 37600ee

Please sign in to comment.