This commit is contained in:
Jack May 2022-06-07 04:45:07 -07:00 committed by GitHub
parent 8674c96a66
commit 363d8d1539
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 126 additions and 76 deletions

4
Cargo.lock generated
View File

@ -6308,9 +6308,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.2.30"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4df28dcb607dd56ab0022f99d3a9ff1ee0d87951315762c0b89e946c087ebbea"
checksum = "80a28c5dfe7e8af38daa39d6561c8e8b9ed7a2f900951ebe7362ad6348d36c73"
dependencies = [
"byteorder",
"combine",

View File

@ -42,7 +42,7 @@ solana-sdk = { path = "../sdk", version = "=1.11.0" }
solana-transaction-status = { path = "../transaction-status", version = "=1.11.0" }
solana-version = { path = "../version", version = "=1.11.0" }
solana-vote-program = { path = "../programs/vote", version = "=1.11.0" }
solana_rbpf = "=0.2.30"
solana_rbpf = "=0.2.31"
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
thiserror = "1.0.31"
tiny-bip39 = "0.8.2"

View File

@ -25,7 +25,11 @@ use {
tpu_client::{TpuClient, TpuClientConfig},
},
solana_program_runtime::invoke_context::InvokeContext,
solana_rbpf::{elf::Executable, verifier, vm::Config},
solana_rbpf::{
elf::Executable,
verifier::RequisiteVerifier,
vm::{Config, VerifiedExecutable},
},
solana_remote_wallet::remote_wallet::RemoteWalletManager,
solana_sdk::{
account::Account,
@ -2079,9 +2083,8 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Verify the program
Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
&program_data,
Some(verifier::check),
Config {
reject_broken_elfs: true,
..Config::default()
@ -2090,6 +2093,12 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
)
.map_err(|err| format!("ELF error: {}", err))?;
let _ =
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
executable,
)
.map_err(|err| format!("ELF error: {}", err))?;
Ok(program_data)
}

View File

@ -5516,9 +5516,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.2.30"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4df28dcb607dd56ab0022f99d3a9ff1ee0d87951315762c0b89e946c087ebbea"
checksum = "80a28c5dfe7e8af38daa39d6561c8e8b9ed7a2f900951ebe7362ad6348d36c73"
dependencies = [
"byteorder 1.4.3",
"combine",

View File

@ -33,7 +33,7 @@ solana-bpf-rust-realloc-invoke = { path = "rust/realloc_invoke", version = "=1.1
solana-cli-output = { path = "../../cli-output", version = "=1.11.0" }
solana-logger = { path = "../../logger", version = "=1.11.0" }
solana-measure = { path = "../../measure", version = "=1.11.0" }
solana_rbpf = "=0.2.30"
solana_rbpf = "=0.2.31"
solana-runtime = { path = "../../runtime", version = "=1.11.0" }
solana-program-runtime = { path = "../../program-runtime", version = "=1.11.0" }
solana-sdk = { path = "../../sdk", version = "=1.11.0" }

View File

@ -15,7 +15,8 @@ use {
solana_program_runtime::invoke_context::with_mock_invoke_context,
solana_rbpf::{
elf::Executable,
vm::{Config, InstructionMeter, SyscallRegistry},
verifier::RequisiteVerifier,
vm::{Config, InstructionMeter, SyscallRegistry, VerifiedExecutable},
},
solana_runtime::{
bank::Bank,
@ -81,7 +82,6 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
bencher.iter(|| {
let _ = Executable::<BpfError, ThisInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
SyscallRegistry::default(),
)
@ -105,17 +105,30 @@ fn bench_program_alu(bencher: &mut Bencher) {
.get_compute_meter()
.borrow_mut()
.mock_set_remaining(std::i64::MAX as u64);
let mut executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
register_syscalls(invoke_context, true).unwrap(),
)
.unwrap();
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
let mut verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
verified_executable.jit_compile().unwrap();
let compute_meter = invoke_context.get_compute_meter();
let mut instruction_meter = ThisInstructionMeter { compute_meter };
let mut vm = create_vm(&executable, &mut inner_iter, vec![], invoke_context).unwrap();
let mut vm = create_vm(
&verified_executable,
&mut inner_iter,
vec![],
invoke_context,
)
.unwrap();
println!("Interpreted:");
assert_eq!(
@ -222,15 +235,21 @@ fn bench_create_vm(bencher: &mut Bencher) {
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
register_syscalls(invoke_context, true).unwrap(),
)
.unwrap();
let verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
bencher.iter(|| {
let _ = create_vm(
&executable,
&verified_executable,
serialized.as_slice_mut(),
account_lengths.clone(),
invoke_context,
@ -263,15 +282,22 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
&elf,
None,
Config::default(),
register_syscalls(invoke_context, true).unwrap(),
)
.unwrap();
let verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
let compute_meter = invoke_context.get_compute_meter();
let mut instruction_meter = ThisInstructionMeter { compute_meter };
let mut vm = create_vm(
&executable,
&verified_executable,
serialized.as_slice_mut(),
account_lengths,
invoke_context,

View File

@ -25,7 +25,8 @@ use {
solana_rbpf::{
elf::Executable,
static_analysis::Analysis,
vm::{Config, Tracer},
verifier::RequisiteVerifier,
vm::{Config, Tracer, VerifiedExecutable},
},
solana_runtime::{
bank::{
@ -222,14 +223,20 @@ fn run_program(name: &str) -> u64 {
reject_broken_elfs: true,
..Config::default()
};
let mut executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
&data,
None,
config,
register_syscalls(invoke_context, true /* no sol_alloc_free */).unwrap(),
)
.unwrap();
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
let mut verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
verified_executable.jit_compile().unwrap();
let mut instruction_count = 0;
let mut tracer = None;
@ -247,7 +254,7 @@ fn run_program(name: &str) -> u64 {
let mut parameter_bytes = parameter_bytes.clone();
{
let mut vm = create_vm(
&executable,
&verified_executable,
parameter_bytes.as_slice_mut(),
account_lengths.clone(),
invoke_context,
@ -266,7 +273,9 @@ fn run_program(name: &str) -> u64 {
if config.enable_instruction_tracing {
if i == 1 {
if !Tracer::compare(tracer.as_ref().unwrap(), vm.get_tracer()) {
let analysis = Analysis::from_executable(&executable).unwrap();
let analysis =
Analysis::from_executable(verified_executable.get_executable())
.unwrap();
let stdout = std::io::stdout();
println!("TRACE (interpreted):");
tracer
@ -280,7 +289,9 @@ fn run_program(name: &str) -> u64 {
.unwrap();
assert!(false);
} else if log_enabled!(Trace) {
let analysis = Analysis::from_executable(&executable).unwrap();
let analysis =
Analysis::from_executable(verified_executable.get_executable())
.unwrap();
let mut trace_buffer = Vec::<u8>::new();
tracer
.as_ref()

View File

@ -19,7 +19,7 @@ solana-metrics = { path = "../../metrics", version = "=1.11.0" }
solana-program-runtime = { path = "../../program-runtime", version = "=1.11.0" }
solana-sdk = { path = "../../sdk", version = "=1.11.0" }
solana-zk-token-sdk = { path = "../../zk-token-sdk", version = "=1.11.0" }
solana_rbpf = "=0.2.30"
solana_rbpf = "=0.2.31"
thiserror = "1.0"
[dev-dependencies]

View File

@ -33,8 +33,8 @@ use {
error::{EbpfError, UserDefinedError},
memory_region::MemoryRegion,
static_analysis::Analysis,
verifier::{self, VerifierError},
vm::{Config, EbpfVm, InstructionMeter},
verifier::{RequisiteVerifier, VerifierError},
vm::{Config, EbpfVm, InstructionMeter, VerifiedExecutable},
},
solana_sdk::{
bpf_loader, bpf_loader_deprecated,
@ -57,7 +57,7 @@ use {
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
transaction_context::{InstructionContext, TransactionContext},
},
std::{cell::RefCell, fmt::Debug, pin::Pin, rc::Rc, sync::Arc},
std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc},
thiserror::Error,
};
@ -158,7 +158,7 @@ pub fn create_executor(
// Warning, do not use `Config::default()` so that configuration here is explicit.
};
let mut create_executor_metrics = executor_metrics::CreateMetrics::default();
let mut executable = {
let executable = {
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context.get_current_instruction_context()?;
let programdata = instruction_context
@ -170,7 +170,6 @@ pub fn create_executor(
.get_data()
.get(programdata_offset..)
.ok_or(InstructionError::AccountDataTooSmall)?,
None,
config,
syscall_registry,
);
@ -183,10 +182,12 @@ pub fn create_executor(
executable
}
.map_err(|e| map_ebpf_error(invoke_context, e))?;
let text_bytes = executable.get_text_bytes().1;
let mut verify_code_time = Measure::start("verify_code_time");
verifier::check(text_bytes, &config)
.map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e.into())))?;
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
executable,
)
.map_err(|e| map_ebpf_error(invoke_context, e))?;
verify_code_time.stop();
create_executor_metrics.verify_code_us = verify_code_time.as_us();
invoke_context.timings.create_executor_verify_code_us = invoke_context
@ -195,8 +196,7 @@ pub fn create_executor(
.saturating_add(create_executor_metrics.verify_code_us);
if use_jit {
let mut jit_compile_time = Measure::start("jit_compile_time");
let jit_compile_result =
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable);
let jit_compile_result = verified_executable.jit_compile();
jit_compile_time.stop();
create_executor_metrics.jit_compile_us = jit_compile_time.as_us();
invoke_context.timings.create_executor_jit_compile_us = invoke_context
@ -210,7 +210,7 @@ pub fn create_executor(
}
create_executor_metrics.submit_datapoint();
Ok(Arc::new(BpfExecutor {
executable,
verified_executable,
use_jit,
}))
}
@ -250,11 +250,11 @@ fn check_loader_id(id: &Pubkey) -> bool {
/// Create the BPF virtual machine
pub fn create_vm<'a, 'b>(
program: &'a Pin<Box<Executable<BpfError, ThisInstructionMeter>>>,
program: &'a VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
parameter_bytes: &mut [u8],
orig_account_lengths: Vec<usize>,
invoke_context: &'a mut InvokeContext<'b>,
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
) -> Result<EbpfVm<'a, RequisiteVerifier, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
let compute_budget = invoke_context.get_compute_budget();
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
if invoke_context
@ -1157,7 +1157,7 @@ impl InstructionMeter for ThisInstructionMeter {
/// BPF Loader's Executor implementation
pub struct BpfExecutor {
executable: Pin<Box<Executable<BpfError, ThisInstructionMeter>>>,
verified_executable: VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
use_jit: bool,
}
@ -1190,7 +1190,7 @@ impl Executor for BpfExecutor {
let mut execute_time;
let execution_result = {
let mut vm = match create_vm(
&self.executable,
&self.verified_executable,
parameter_bytes.as_slice_mut(),
account_lengths,
invoke_context,
@ -1222,7 +1222,8 @@ impl Executor for BpfExecutor {
);
if log_enabled!(Trace) {
let mut trace_buffer = Vec::<u8>::new();
let analysis = Analysis::from_executable(&self.executable).unwrap();
let analysis =
Analysis::from_executable(self.verified_executable.get_executable()).unwrap();
vm.get_tracer().write(&mut trace_buffer, &analysis).unwrap();
let trace_string = String::from_utf8(trace_buffer).unwrap();
trace!("BPF Program Instruction Trace:\n{}", trace_string);
@ -1305,7 +1306,7 @@ mod tests {
super::*,
rand::Rng,
solana_program_runtime::invoke_context::mock_process_instruction,
solana_rbpf::vm::SyscallRegistry,
solana_rbpf::{verifier::Verifier, vm::SyscallRegistry},
solana_runtime::{bank::Bank, bank_client::BankClient},
solana_sdk::{
account::{
@ -1374,6 +1375,13 @@ mod tests {
program_account
}
struct TautologyVerifier {}
impl Verifier for TautologyVerifier {
fn verify(_prog: &[u8], _config: &Config) -> std::result::Result<(), VerifierError> {
Ok(())
}
}
#[test]
#[should_panic(expected = "ExceededMaxInstructions(31, 10)")]
fn test_bpf_loader_non_terminating_program() {
@ -1395,18 +1403,21 @@ mod tests {
"entrypoint",
)
.unwrap();
let program = Executable::<BpfError, TestInstructionMeter>::from_text_bytes(
let executable = Executable::<BpfError, TestInstructionMeter>::from_text_bytes(
program,
None,
config,
syscall_registry,
bpf_functions,
)
.unwrap();
let verified_executable = VerifiedExecutable::<
TautologyVerifier,
BpfError,
TestInstructionMeter,
>::from_executable(executable)
.unwrap();
let input_region = MemoryRegion::new_writable(&mut input_mem, MM_INPUT_START);
let mut vm =
EbpfVm::<BpfError, TestInstructionMeter>::new(&program, &mut [], vec![input_region])
.unwrap();
let mut vm = EbpfVm::new(&verified_executable, &mut [], vec![input_region]).unwrap();
let mut instruction_meter = TestInstructionMeter { remaining: 10 };
vm.execute_program_interpreted(&mut instruction_meter)
.unwrap();
@ -1418,7 +1429,7 @@ mod tests {
let prog = &[
0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw
];
verifier::check(prog, &Config::default()).unwrap();
RequisiteVerifier::verify(prog, &Config::default()).unwrap();
}
#[test]

View File

@ -13,6 +13,7 @@ use {
error::EbpfError,
memory_region::{AccessType, MemoryMapping},
question_mark,
verifier::RequisiteVerifier,
vm::{EbpfVm, SyscallObject, SyscallRegistry},
},
solana_sdk::{
@ -384,7 +385,7 @@ pub fn register_syscalls(
}
pub fn bind_syscall_context_objects<'a, 'b>(
vm: &mut EbpfVm<'a, BpfError, crate::ThisInstructionMeter>,
vm: &mut EbpfVm<'a, RequisiteVerifier, BpfError, crate::ThisInstructionMeter>,
invoke_context: &'a mut InvokeContext<'b>,
heap: AlignedMemory,
orig_account_lengths: Vec<usize>,

View File

@ -17,4 +17,4 @@ solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.11.
solana-logger = { path = "../logger", version = "=1.11.0" }
solana-program-runtime = { path = "../program-runtime", version = "=1.11.0" }
solana-sdk = { path = "../sdk", version = "=1.11.0" }
solana_rbpf = "=0.2.30"
solana_rbpf = "=0.2.31"

View File

@ -11,8 +11,8 @@ use {
assembler::assemble,
elf::Executable,
static_analysis::Analysis,
verifier::check,
vm::{Config, DynamicAnalysis},
verifier::RequisiteVerifier,
vm::{Config, DynamicAnalysis, VerifiedExecutable},
},
solana_sdk::{
account::AccountSharedData, bpf_loader, instruction::AccountMeta, pubkey::Pubkey,
@ -152,12 +152,6 @@ native machine code before execting it in the virtual machine.",
.short('p')
.long("profile"),
)
.arg(
Arg::new("verify")
.help("Run the verifier before execution or disassembly")
.short('v')
.long("verify"),
)
.arg(
Arg::new("output_format")
.help("Return information in specified output format")
@ -250,30 +244,27 @@ native machine code before execting it in the virtual machine.",
let mut contents = Vec::new();
file.read_to_end(&mut contents).unwrap();
let syscall_registry = register_syscalls(&mut invoke_context, true).unwrap();
let mut executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
Executable::<BpfError, ThisInstructionMeter>::from_elf(
&contents,
None,
config,
syscall_registry,
)
.map_err(|err| format!("Executable constructor failed: {:?}", err))
let executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
Executable::<BpfError, ThisInstructionMeter>::from_elf(&contents, config, syscall_registry)
.map_err(|err| format!("Executable constructor failed: {:?}", err))
} else {
assemble::<BpfError, ThisInstructionMeter>(
std::str::from_utf8(contents.as_slice()).unwrap(),
None,
config,
syscall_registry,
)
}
.unwrap();
if matches.is_present("verify") {
let text_bytes = executable.get_text_bytes().1;
check(text_bytes, &config).unwrap();
}
Executable::<BpfError, ThisInstructionMeter>::jit_compile(&mut executable).unwrap();
let mut analysis = LazyAnalysis::new(&executable);
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
executable,
)
.map_err(|err| format!("Executable verifier failed: {:?}", err))
.unwrap();
verified_executable.jit_compile().unwrap();
let mut analysis = LazyAnalysis::new(verified_executable.get_executable());
match matches.value_of("use") {
Some("cfg") => {
@ -293,7 +284,7 @@ native machine code before execting it in the virtual machine.",
}
let mut vm = create_vm(
&executable,
&verified_executable,
parameter_bytes.as_slice_mut(),
account_lengths,
&mut invoke_context,

View File

@ -0,0 +1 @@
/Users/jack/.cache/solana/v1.27/sbf-tools