From fca8d5cf67e8582caad81c0df29ef10beba81bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Fri, 3 Dec 2021 21:50:14 +0100 Subject: [PATCH] Bump solana_rbpf to version v0.2.14 (#18869) * Feature gate for verify_mul64_imm_nonzero as discussed in #17520. --- Cargo.lock | 4 +- cli/Cargo.toml | 2 +- cli/src/program.rs | 3 +- programs/bpf/Cargo.lock | 4 +- programs/bpf/Cargo.toml | 2 +- programs/bpf_loader/Cargo.toml | 2 +- programs/bpf_loader/src/lib.rs | 29 +- programs/bpf_loader/src/syscalls.rs | 428 ++++++++++++++++------------ rbpf-cli/Cargo.toml | 2 +- rbpf-cli/src/main.rs | 4 +- sdk/src/feature_set.rs | 5 + 11 files changed, 273 insertions(+), 212 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b54d3cebc96c14..5c7709b47087af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5951,9 +5951,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1dced9892c2b0273318ef4d8486112ea7c7a7b8eb563a20e7858ad921b4719" +checksum = "e27486ed1c74044866b529076b6aa9ca6fab9ec494d1835439ec84efc5575953" dependencies = [ "byteorder", "combine", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 7f78587737d985..583560fc33796c 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -40,7 +40,7 @@ solana-config-program = { path = "../programs/config", version = "=1.8.7" } solana-faucet = { path = "../faucet", version = "=1.8.7" } solana-logger = { path = "../logger", version = "=1.8.7" } solana-net-utils = { path = "../net-utils", version = "=1.8.7" } -solana_rbpf = "=0.2.13" +solana_rbpf = "=0.2.14" solana-remote-wallet = { path = "../remote-wallet", version = "=1.8.7" } solana-sdk = { path = "../sdk", version = "=1.8.7" } solana-transaction-status = { path = "../transaction-status", version = "=1.8.7" } diff --git a/cli/src/program.rs b/cli/src/program.rs index c1ba6b2c7c839c..7e597b6f997b32 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -1991,9 +1991,10 @@ fn read_and_verify_elf(program_location: &str) -> Result, Box>::from_elf( &program_data, - Some(|x| verifier::check(x)), + Some(verifier::check), Config { reject_unresolved_syscalls: true, + verify_mul64_imm_nonzero: true, // TODO: Remove me after feature gate ..Config::default() }, register_syscalls(&mut invoke_context).unwrap(), diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index faf97729294e8a..57bc4e07c15dc8 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3698,9 +3698,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1dced9892c2b0273318ef4d8486112ea7c7a7b8eb563a20e7858ad921b4719" +checksum = "e27486ed1c74044866b529076b6aa9ca6fab9ec494d1835439ec84efc5575953" dependencies = [ "byteorder 1.3.4", "combine", diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index f919de3674c48d..e0f857743768a2 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -30,7 +30,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.8.7" } solana-cli-output = { path = "../../cli-output", version = "=1.8.7" } solana-logger = { path = "../../logger", version = "=1.8.7" } solana-measure = { path = "../../measure", version = "=1.8.7" } -solana_rbpf = "=0.2.13" +solana_rbpf = "=0.2.14" solana-runtime = { path = "../../runtime", version = "=1.8.7" } solana-sdk = { path = "../../sdk", version = "=1.8.7" } solana-transaction-status = { path = "../../transaction-status", version = "=1.8.7" } diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index f1f5879ac187c3..d4de0d89a17251 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -21,7 +21,7 @@ sha3 = "0.9.1" solana-measure = { path = "../../measure", version = "=1.8.7" } solana-runtime = { path = "../../runtime", version = "=1.8.7" } solana-sdk = { path = "../../sdk", version = "=1.8.7" } -solana_rbpf = "=0.2.13" +solana_rbpf = "=0.2.14" thiserror = "1.0" [dev-dependencies] diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 13fd075c1fc54d..73547d922bc78c 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -17,9 +17,8 @@ use { solana_measure::measure::Measure, solana_rbpf::{ aligned_memory::AlignedMemory, - ebpf::{HOST_ALIGN, MM_HEAP_START}, + ebpf::HOST_ALIGN, error::{EbpfError, UserDefinedError}, - memory_region::MemoryRegion, static_analysis::Analysis, verifier::{self, VerifierError}, vm::{Config, EbpfVm, Executable, InstructionMeter}, @@ -35,7 +34,7 @@ use { feature_set::{ add_missing_program_error_mappings, close_upgradeable_program_accounts, fix_write_privs, reduce_required_deploy_balance, requestable_heap_size, - upgradeable_close_instruction, + stop_verify_mul64_imm_nonzero, upgradeable_close_instruction, }, ic_logger_msg, ic_msg, instruction::{AccountMeta, InstructionError}, @@ -89,6 +88,8 @@ pub fn create_executor( max_call_depth: bpf_compute_budget.max_call_depth, stack_frame_size: bpf_compute_budget.stack_frame_size, enable_instruction_tracing: log_enabled!(Trace), + verify_mul64_imm_nonzero: !invoke_context + .is_feature_active(&stop_verify_mul64_imm_nonzero::id()), // TODO: Feature gate and then remove me ..Config::default() }; let mut executable = { @@ -104,10 +105,8 @@ pub fn create_executor( ) } .map_err(|e| map_ebpf_error(invoke_context, e))?; - let (_, elf_bytes) = executable - .get_text_bytes() - .map_err(|e| map_ebpf_error(invoke_context, e))?; - verifier::check(elf_bytes) + let text_bytes = executable.get_text_bytes().1; + verifier::check(text_bytes, &config) .map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e.into())))?; if use_jit { if let Err(err) = executable.jit_compile() { @@ -156,18 +155,11 @@ pub fn create_vm<'a>( invoke_context: &'a mut dyn InvokeContext, ) -> Result, EbpfError> { let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); - let heap_size = bpf_compute_budget.heap_size.unwrap_or(HEAP_LENGTH); - if invoke_context.is_feature_active(&requestable_heap_size::id()) { - let _ = invoke_context.get_compute_meter().borrow_mut().consume( - (heap_size as u64 / (32 * 1024)).saturating_sub(1) * bpf_compute_budget.heap_cost, - ); - } - let heap = AlignedMemory::new_with_size( + let mut heap = AlignedMemory::new_with_size( bpf_compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN, ); - let heap_region = MemoryRegion::new_from_slice(heap.as_slice(), MM_HEAP_START, 0, true); - let mut vm = EbpfVm::new(program, parameter_bytes, &[heap_region])?; + let mut vm = EbpfVm::new(program, heap.as_slice_mut(), parameter_bytes)?; syscalls::bind_syscall_context_objects(loader_id, &mut vm, invoke_context, heap)?; Ok(vm) } @@ -1069,7 +1061,8 @@ mod tests { ) .unwrap(); let mut vm = - EbpfVm::::new(program.as_ref(), input, &[]).unwrap(); + EbpfVm::::new(program.as_ref(), &mut [], input) + .unwrap(); let mut instruction_meter = TestInstructionMeter { remaining: 10 }; vm.execute_program_interpreted(&mut instruction_meter) .unwrap(); @@ -1081,7 +1074,7 @@ mod tests { let prog = &[ 0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw ]; - verifier::check(prog).unwrap(); + verifier::check(prog, &Config::default()).unwrap(); } #[test] diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 32075bc9e56b2b..d8803dfc6e7ce7 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -3,7 +3,7 @@ use { alloc::Alloc, solana_rbpf::{ aligned_memory::AlignedMemory, - ebpf::MM_HEAP_START, + ebpf, error::EbpfError, memory_region::{AccessType, MemoryMapping}, question_mark, @@ -455,7 +455,7 @@ pub fn bind_syscall_context_objects<'a>( vm.bind_syscall_context_object( Box::new(SyscallAllocFree { aligned: *loader_id != bpf_loader_deprecated::id(), - allocator: BpfAllocator::new(heap, MM_HEAP_START), + allocator: BpfAllocator::new(heap, ebpf::MM_HEAP_START), }), None, )?; @@ -2781,7 +2781,9 @@ mod tests { macro_rules! assert_access_violation { ($result:expr, $va:expr, $len:expr) => { match $result { - Err(EbpfError::AccessViolation(_, _, va, len, _)) if $va == va && len == len => (), + Err(EbpfError::AccessViolation(_, _, va, len, _)) if $va == va && $len == len => (), + Err(EbpfError::StackAccessViolation(_, _, va, len, _)) + if $va == va && $len == len => {} _ => panic!(), } }; @@ -2795,13 +2797,16 @@ mod tests { #[test] fn test_translate() { - const START: u64 = 100; + const START: u64 = 0x100000000; const LENGTH: u64 = 1000; let data = vec![0u8; LENGTH as usize]; let addr = data.as_ptr() as u64; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice(&data, START, 0, false)], + vec![ + MemoryRegion::default(), + MemoryRegion::new_from_slice(&data, START, 0, false), + ], &config, ) .unwrap(); @@ -2841,18 +2846,22 @@ mod tests { let addr = &pubkey as *const _ as u64; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let translated_pubkey = - translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).unwrap(); + translate_type::(&memory_mapping, 0x100000000, &bpf_loader::id(), true) + .unwrap(); assert_eq!(pubkey, *translated_pubkey); // Instruction @@ -2863,23 +2872,31 @@ mod tests { ); let addr = &instruction as *const _ as u64; let mut memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 96, - len: std::mem::size_of::() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: std::mem::size_of::() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let translated_instruction = - translate_type::(&memory_mapping, 96, &bpf_loader::id(), true).unwrap(); + translate_type::(&memory_mapping, 0x100000000, &bpf_loader::id(), true) + .unwrap(); assert_eq!(instruction, *translated_instruction); - memory_mapping.resize_region::(0, 1).unwrap(); - assert!( - translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).is_err() - ); + memory_mapping.resize_region::(1, 1).unwrap(); + assert!(translate_type::( + &memory_mapping, + 0x100000000, + &bpf_loader::id(), + true + ) + .is_err()); } #[test] @@ -2891,13 +2908,16 @@ mod tests { let addr = good_data.as_ptr() as *const _ as u64; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: good_data.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: good_data.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); @@ -2916,19 +2936,22 @@ mod tests { let mut data = vec![1u8, 2, 3, 4, 5]; let addr = data.as_ptr() as *const _ as u64; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: data.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: data.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let translated_data = translate_slice::( &memory_mapping, - 100, + 0x100000000, data.len() as u64, &bpf_loader::id(), true, @@ -2948,7 +2971,7 @@ mod tests { assert!(translate_slice::( &memory_mapping, - 100 - 1, + 0x100000000 - 1, data.len() as u64, &bpf_loader::id(), true, @@ -2959,19 +2982,22 @@ mod tests { let mut data = vec![1u64, 2, 3, 4, 5]; let addr = data.as_ptr() as *const _ as u64; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 96, - len: (data.len() * size_of::()) as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: (data.len() * size_of::()) as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let translated_data = translate_slice::( &memory_mapping, - 96, + 0x100000000, data.len() as u64, &bpf_loader::id(), true, @@ -2980,28 +3006,35 @@ mod tests { assert_eq!(data, translated_data); data[0] = 10; assert_eq!(data, translated_data); - assert!( - translate_slice::(&memory_mapping, 96, u64::MAX, &bpf_loader::id(), true,) - .is_err() - ); + assert!(translate_slice::( + &memory_mapping, + 0x100000000, + u64::MAX, + &bpf_loader::id(), + true, + ) + .is_err()); // Pubkeys let mut data = vec![solana_sdk::pubkey::new_rand(); 5]; let addr = data.as_ptr() as *const _ as u64; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: (data.len() * std::mem::size_of::()) as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: (data.len() * std::mem::size_of::()) as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let translated_data = translate_slice::( &memory_mapping, - 100, + 0x100000000, data.len() as u64, &bpf_loader::id(), true, @@ -3018,13 +3051,16 @@ mod tests { let addr = string.as_ptr() as *const _ as u64; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: string.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: string.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); @@ -3032,7 +3068,7 @@ mod tests { 42, translate_string_and_do( &memory_mapping, - 100, + 0x100000000, string.len() as u64, &bpf_loader::id(), true, @@ -3072,13 +3108,16 @@ mod tests { let addr = string.as_ptr() as *const _ as u64; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: string.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: string.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); @@ -3094,7 +3133,7 @@ mod tests { }; let mut result: Result> = Ok(0); syscall_panic.call( - 100, + 0x100000000, string.len() as u64, 42, 84, @@ -3120,7 +3159,7 @@ mod tests { }; let mut result: Result> = Ok(0); syscall_panic.call( - 100, + 0x100000000, string.len() as u64, 42, 84, @@ -3149,20 +3188,23 @@ mod tests { }; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: string.len() as u64, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: string.len() as u64, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let mut result: Result> = Ok(0); syscall_sol_log.call( - 100, + 0x100000000, string.len() as u64, 0, 0, @@ -3176,7 +3218,7 @@ mod tests { let mut result: Result> = Ok(0); syscall_sol_log.call( - 101, // AccessViolation + 0x100000001, // AccessViolation string.len() as u64, 0, 0, @@ -3184,10 +3226,10 @@ mod tests { &memory_mapping, &mut result, ); - assert_access_violation!(result, 101, string.len() as u64); + assert_access_violation!(result, 0x100000001, string.len() as u64); let mut result: Result> = Ok(0); syscall_sol_log.call( - 100, + 0x100000000, string.len() as u64 * 2, // AccessViolation 0, 0, @@ -3195,10 +3237,10 @@ mod tests { &memory_mapping, &mut result, ); - assert_access_violation!(result, 100, string.len() as u64 * 2); + assert_access_violation!(result, 0x100000000, string.len() as u64 * 2); let mut result: Result> = Ok(0); syscall_sol_log.call( - 100, + 0x100000000, string.len() as u64, 0, 0, @@ -3220,7 +3262,7 @@ mod tests { }; let mut result: Result> = Ok(0); syscall_sol_log.call( - 100, + 0x100000000, string.len() as u64, 0, 0, @@ -3231,7 +3273,7 @@ mod tests { result.unwrap(); let mut result: Result> = Ok(0); syscall_sol_log.call( - 100, + 0x100000000, string.len() as u64, 0, 0, @@ -3291,19 +3333,22 @@ mod tests { }; let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: addr, - vm_addr: 100, - len: 32, - vm_gap_shift: 63, - is_writable: false, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: addr, + vm_addr: 0x100000000, + len: 32, + vm_gap_shift: 63, + is_writable: false, + }, + ], &config, ) .unwrap(); let mut result: Result> = Ok(0); - syscall_sol_pubkey.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); + syscall_sol_pubkey.call(0x100000000, 0, 0, 0, 0, &memory_mapping, &mut result); result.unwrap(); assert_eq!(log.borrow().len(), 1); assert_eq!( @@ -3312,7 +3357,7 @@ mod tests { ); let mut result: Result> = Ok(0); syscall_sol_pubkey.call( - 101, // AccessViolation + 0x100000001, // AccessViolation 32, 0, 0, @@ -3320,7 +3365,7 @@ mod tests { &memory_mapping, &mut result, ); - assert_access_violation!(result, 101, 32); + assert_access_violation!(result, 0x100000001, 32); let mut result: Result> = Ok(0); syscall_sol_pubkey.call(100, 32, 0, 0, 0, &memory_mapping, &mut result); assert_eq!( @@ -3338,18 +3383,19 @@ mod tests { { let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], + vec![ + MemoryRegion::default(), + MemoryRegion::new_from_slice(&[], ebpf::MM_PROGRAM_START, 0, false), + MemoryRegion::new_from_slice(&[], ebpf::MM_STACK_START, 4096, true), + MemoryRegion::new_from_slice(heap.as_slice(), ebpf::MM_HEAP_START, 0, true), + MemoryRegion::new_from_slice(&[], ebpf::MM_INPUT_START, 0, true), + ], &config, ) .unwrap(); let mut syscall = SyscallAllocFree { aligned: true, - allocator: BpfAllocator::new(heap, MM_HEAP_START), + allocator: BpfAllocator::new(heap, ebpf::MM_HEAP_START), }; let mut result: Result> = Ok(0); syscall.call(100, 0, 0, 0, 0, &memory_mapping, &mut result); @@ -3365,18 +3411,19 @@ mod tests { { let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], + vec![ + MemoryRegion::default(), + MemoryRegion::new_from_slice(&[], ebpf::MM_PROGRAM_START, 0, false), + MemoryRegion::new_from_slice(&[], ebpf::MM_STACK_START, 4096, true), + MemoryRegion::new_from_slice(heap.as_slice(), ebpf::MM_HEAP_START, 0, true), + MemoryRegion::new_from_slice(&[], ebpf::MM_INPUT_START, 0, true), + ], &config, ) .unwrap(); let mut syscall = SyscallAllocFree { aligned: false, - allocator: BpfAllocator::new(heap, MM_HEAP_START), + allocator: BpfAllocator::new(heap, ebpf::MM_HEAP_START), }; for _ in 0..100 { let mut result: Result> = Ok(0); @@ -3391,18 +3438,19 @@ mod tests { { let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], + vec![ + MemoryRegion::default(), + MemoryRegion::new_from_slice(&[], ebpf::MM_PROGRAM_START, 0, false), + MemoryRegion::new_from_slice(&[], ebpf::MM_STACK_START, 4096, true), + MemoryRegion::new_from_slice(heap.as_slice(), ebpf::MM_HEAP_START, 0, true), + MemoryRegion::new_from_slice(&[], ebpf::MM_INPUT_START, 0, true), + ], &config, ) .unwrap(); let mut syscall = SyscallAllocFree { aligned: true, - allocator: BpfAllocator::new(heap, MM_HEAP_START), + allocator: BpfAllocator::new(heap, ebpf::MM_HEAP_START), }; for _ in 0..12 { let mut result: Result> = Ok(0); @@ -3419,18 +3467,19 @@ mod tests { let heap = AlignedMemory::new_with_size(100, HOST_ALIGN); let config = Config::default(); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice( - heap.as_slice(), - MM_HEAP_START, - 0, - true, - )], + vec![ + MemoryRegion::default(), + MemoryRegion::new_from_slice(&[], ebpf::MM_PROGRAM_START, 0, false), + MemoryRegion::new_from_slice(&[], ebpf::MM_STACK_START, 4096, true), + MemoryRegion::new_from_slice(heap.as_slice(), ebpf::MM_HEAP_START, 0, true), + MemoryRegion::new_from_slice(&[], ebpf::MM_INPUT_START, 0, true), + ], &config, ) .unwrap(); let mut syscall = SyscallAllocFree { aligned: true, - allocator: BpfAllocator::new(heap, MM_HEAP_START), + allocator: BpfAllocator::new(heap, ebpf::MM_HEAP_START), }; let mut result: Result> = Ok(0); syscall.call( @@ -3459,48 +3508,49 @@ mod tests { let bytes2 = "flurbos"; let mock_slice1 = MockSlice { - vm_addr: 4096, + vm_addr: 0x300000000, len: bytes1.len(), }; let mock_slice2 = MockSlice { - vm_addr: 8192, + vm_addr: 0x400000000, len: bytes2.len(), }; let bytes_to_hash = [mock_slice1, mock_slice2]; let hash_result = [0; HASH_BYTES]; let ro_len = bytes_to_hash.len() as u64; - let ro_va = 96; - let rw_va = 192; + let ro_va = 0x100000000; + let rw_va = 0x200000000; let config = Config::default(); let memory_mapping = MemoryMapping::new::( vec![ + MemoryRegion::default(), MemoryRegion { - host_addr: bytes1.as_ptr() as *const _ as u64, - vm_addr: 4096, - len: bytes1.len() as u64, + host_addr: bytes_to_hash.as_ptr() as *const _ as u64, + vm_addr: ro_va, + len: 32, vm_gap_shift: 63, is_writable: false, }, MemoryRegion { - host_addr: bytes2.as_ptr() as *const _ as u64, - vm_addr: 8192, - len: bytes2.len() as u64, + host_addr: hash_result.as_ptr() as *const _ as u64, + vm_addr: rw_va, + len: HASH_BYTES as u64, vm_gap_shift: 63, - is_writable: false, + is_writable: true, }, MemoryRegion { - host_addr: bytes_to_hash.as_ptr() as *const _ as u64, - vm_addr: 96, - len: 32, + host_addr: bytes1.as_ptr() as *const _ as u64, + vm_addr: bytes_to_hash[0].vm_addr, + len: bytes1.len() as u64, vm_gap_shift: 63, is_writable: false, }, MemoryRegion { - host_addr: hash_result.as_ptr() as *const _ as u64, - vm_addr: rw_va, - len: HASH_BYTES as u64, + host_addr: bytes2.as_ptr() as *const _ as u64, + vm_addr: bytes_to_hash[1].vm_addr, + len: bytes2.len() as u64, vm_gap_shift: 63, - is_writable: true, + is_writable: false, }, ], &config, @@ -3534,7 +3584,7 @@ mod tests { &memory_mapping, &mut result, ); - assert_access_violation!(result, ro_va - 1, ro_len); + assert_access_violation!(result, ro_va - 1, 32); let mut result: Result> = Ok(0); syscall.call( ro_va, @@ -3545,7 +3595,7 @@ mod tests { &memory_mapping, &mut result, ); - assert_access_violation!(result, ro_va, ro_len + 1); + assert_access_violation!(result, ro_va, 48); let mut result: Result> = Ok(0); syscall.call( ro_va, @@ -3573,16 +3623,19 @@ mod tests { // Test clock sysvar { let got_clock = Clock::default(); - let got_clock_va = 2048; + let got_clock_va = 0x100000000; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_clock as *const _ as u64, - vm_addr: got_clock_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: &got_clock as *const _ as u64, + vm_addr: got_clock_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], &config, ) .unwrap(); @@ -3615,16 +3668,19 @@ mod tests { // Test epoch_schedule sysvar { let got_epochschedule = EpochSchedule::default(); - let got_epochschedule_va = 2048; + let got_epochschedule_va = 0x100000000; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_epochschedule as *const _ as u64, - vm_addr: got_epochschedule_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: &got_epochschedule as *const _ as u64, + vm_addr: got_epochschedule_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], &config, ) .unwrap(); @@ -3665,16 +3721,19 @@ mod tests { // Test fees sysvar { let got_fees = Fees::default(); - let got_fees_va = 2048; + let got_fees_va = 0x100000000; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_fees as *const _ as u64, - vm_addr: got_fees_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: &got_fees as *const _ as u64, + vm_addr: got_fees_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], &config, ) .unwrap(); @@ -3705,16 +3764,19 @@ mod tests { // Test rent sysvar { let got_rent = Rent::default(); - let got_rent_va = 2048; + let got_rent_va = 0x100000000; let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion { - host_addr: &got_rent as *const _ as u64, - vm_addr: got_rent_va, - len: size_of::() as u64, - vm_gap_shift: 63, - is_writable: true, - }], + vec![ + MemoryRegion::default(), + MemoryRegion { + host_addr: &got_rent as *const _ as u64, + vm_addr: got_rent_va, + len: size_of::() as u64, + vm_gap_shift: 63, + is_writable: true, + }, + ], &config, ) .unwrap(); diff --git a/rbpf-cli/Cargo.toml b/rbpf-cli/Cargo.toml index 1b058779fb6d40..9b53f97200cfac 100644 --- a/rbpf-cli/Cargo.toml +++ b/rbpf-cli/Cargo.toml @@ -15,4 +15,4 @@ serde_json = "1.0.56" solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.8.7" } solana-logger = { path = "../logger", version = "=1.8.7" } solana-sdk = { path = "../sdk", version = "=1.8.7" } -solana_rbpf = "=0.2.13" +solana_rbpf = "=0.2.14" diff --git a/rbpf-cli/src/main.rs b/rbpf-cli/src/main.rs index 39ba349bddcece..985f2ea0f0d181 100644 --- a/rbpf-cli/src/main.rs +++ b/rbpf-cli/src/main.rs @@ -205,8 +205,8 @@ native machine code before execting it in the virtual machine.", .unwrap(); if matches.is_present("verify") { - let (_, elf_bytes) = executable.get_text_bytes().unwrap(); - check(elf_bytes).unwrap(); + let text_bytes = executable.get_text_bytes().1; + check(text_bytes, &config).unwrap(); } executable.jit_compile().unwrap(); let analysis = Analysis::from_executable(executable.as_ref()); diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index c3dc05879a1187..fe6d843a76cf0d 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -165,6 +165,10 @@ pub mod libsecp256k1_0_5_upgrade_enabled { solana_sdk::declare_id!("DhsYfRjxfnh2g7HKJYSzT79r74Afa1wbHkAgHndrA1oy"); } +pub mod stop_verify_mul64_imm_nonzero { + solana_sdk::declare_id!("EHFwHg2vhwUb7ifm7BuY9RMbsyt1rS1rUii7yeDJtGnN"); +} + pub mod merge_nonce_error_into_system_error { solana_sdk::declare_id!("21AWDosvp3pBamFW91KB35pNoaoZVTM7ess8nr2nt53B"); } @@ -298,6 +302,7 @@ lazy_static! { (neon_evm_compute_budget::id(), "bump neon_evm's compute budget"), (rent_for_sysvars::id(), "collect rent from accounts owned by sysvars"), (libsecp256k1_0_5_upgrade_enabled::id(), "upgrade libsecp256k1 to v0.5.0"), + (stop_verify_mul64_imm_nonzero::id(), "Sets rbpf vm config verify_mul64_imm_nonzero to false"), (merge_nonce_error_into_system_error::id(), "merge NonceError into SystemError"), (spl_token_v2_set_authority_fix::id(), "spl-token set_authority fix"), (stake_merge_with_unmatched_credits_observed::id(), "allow merging active stakes with unmatched credits_observed #18985"),