diff --git a/Cargo.lock b/Cargo.lock index da1b1091eb..ed7c2a05bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5550,9 +5550,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e36c51d5aa290416c5dea3c43ac467cb57c0b643184af23e6bdab7434710fb" +checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e" dependencies = [ "byteorder", "combine", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 762c9011f6..6adb3b3b1d 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -38,7 +38,7 @@ solana-config-program = { path = "../programs/config", version = "=1.6.7" } solana-faucet = { path = "../faucet", version = "=1.6.7" } solana-logger = { path = "../logger", version = "=1.6.7" } solana-net-utils = { path = "../net-utils", version = "=1.6.7" } -solana_rbpf = "=0.2.7" +solana_rbpf = "=0.2.8" solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.7" } solana-sdk = { path = "../sdk", version = "=1.6.7" } solana-stake-program = { path = "../programs/stake", version = "=1.6.7" } diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index e9976dbd10..687674f433 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3527,9 +3527,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e36c51d5aa290416c5dea3c43ac467cb57c0b643184af23e6bdab7434710fb" +checksum = "7fcec120278017a67e2dd98494dfdd8e565f53f1d05ab558d1656c369c5dd95e" dependencies = [ "byteorder 1.3.4", "combine", diff --git a/programs/bpf/Cargo.toml b/programs/bpf/Cargo.toml index f5d799a3f7..c20e6dc4c1 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -29,7 +29,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.6.7" } solana-cli-output = { path = "../../cli-output", version = "=1.6.7" } solana-logger = { path = "../../logger", version = "=1.6.7" } solana-measure = { path = "../../measure", version = "=1.6.7" } -solana_rbpf = "=0.2.7" +solana_rbpf = "=0.2.8" solana-runtime = { path = "../../runtime", version = "=1.6.7" } solana-sdk = { path = "../../sdk", version = "=1.6.7" } solana-transaction-status = { path = "../../transaction-status", version = "=1.6.7" } diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index 926eff8e79..a52d8f03e5 100644 --- a/programs/bpf/benches/bpf_loader.rs +++ b/programs/bpf/benches/bpf_loader.rs @@ -75,9 +75,12 @@ fn bench_program_create_executable(bencher: &mut Bencher) { let elf = load_elf("bench_alu").unwrap(); bencher.iter(|| { - let _ = - Executable::::from_elf(&elf, None, Config::default()) - .unwrap(); + let _ = >::from_elf( + &elf, + None, + Config::default(), + ) + .unwrap(); }); } @@ -95,7 +98,7 @@ fn bench_program_alu(bencher: &mut Bencher) { let elf = load_elf("bench_alu").unwrap(); let mut executable = - Executable::::from_elf(&elf, None, Config::default()) + >::from_elf(&elf, None, Config::default()) .unwrap(); executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap()); executable.jit_compile().unwrap(); @@ -222,7 +225,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { let elf = load_elf("tuner").unwrap(); let mut executable = - Executable::::from_elf(&elf, None, Config::default()) + >::from_elf(&elf, None, Config::default()) .unwrap(); executable.set_syscall_registry(register_syscalls(&mut invoke_context).unwrap()); let compute_meter = invoke_context.get_compute_meter(); @@ -230,7 +233,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { let mut vm = create_vm( &loader_id, executable.as_ref(), - &mut serialized, + serialized.as_slice_mut(), &[], &mut invoke_context, ) diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 0060196b20..4e9b804569 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -219,7 +219,7 @@ fn run_program( let mut vm = create_vm( &loader_id, executable.as_ref(), - &mut parameter_bytes, + parameter_bytes.as_slice_mut(), parameter_accounts, &mut invoke_context, ) @@ -233,7 +233,7 @@ fn run_program( deserialize_parameters( &bpf_loader::id(), parameter_accounts, - ¶meter_bytes, + parameter_bytes.as_slice(), true, ) .unwrap(); diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index 2a194334d9..f5070bfb6f 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -20,7 +20,7 @@ rand_core = "0.6.2" solana-measure = { path = "../../measure", version = "=1.6.7" } solana-runtime = { path = "../../runtime", version = "=1.6.7" } solana-sdk = { path = "../../sdk", version = "=1.6.7" } -solana_rbpf = "=0.2.7" +solana_rbpf = "=0.2.8" thiserror = "1.0" [dev-dependencies] diff --git a/programs/bpf_loader/src/allocator_bump.rs b/programs/bpf_loader/src/allocator_bump.rs index 05d68ba912..ea3fee8fd1 100644 --- a/programs/bpf_loader/src/allocator_bump.rs +++ b/programs/bpf_loader/src/allocator_bump.rs @@ -1,18 +1,19 @@ use crate::alloc; use alloc::{Alloc, AllocErr}; +use solana_rbpf::aligned_memory::AlignedMemory; use std::alloc::Layout; #[derive(Debug)] pub struct BpfAllocator { - heap: Vec, + heap: AlignedMemory, start: u64, len: u64, pos: u64, } impl BpfAllocator { - pub fn new(heap: Vec, virtual_address: u64) -> Self { + pub fn new(heap: AlignedMemory, virtual_address: u64) -> Self { let len = heap.len() as u64; Self { heap, diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 0f65ccedaf..285ae30bed 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -17,7 +17,8 @@ use crate::{ use log::{log_enabled, trace, Level::Trace}; use solana_measure::measure::Measure; use solana_rbpf::{ - ebpf::MM_HEAP_START, + aligned_memory::AlignedMemory, + ebpf::{HOST_ALIGN, MM_HEAP_START}, error::{EbpfError, UserDefinedError}, memory_region::MemoryRegion, vm::{Config, EbpfVm, Executable, InstructionMeter}, @@ -146,8 +147,8 @@ pub fn create_vm<'a>( parameter_accounts: &'a [KeyedAccount<'a>], invoke_context: &'a mut dyn InvokeContext, ) -> Result, EbpfError> { - let heap = vec![0_u8; DEFAULT_HEAP_SIZE]; - let heap_region = MemoryRegion::new_from_slice(&heap, MM_HEAP_START, 0, true); + let heap = AlignedMemory::new(DEFAULT_HEAP_SIZE, 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])?; syscalls::bind_syscall_context_objects( loader_id, @@ -793,7 +794,7 @@ impl Executor for BpfExecutor { let mut vm = match create_vm( loader_id, self.program.as_ref(), - &mut parameter_bytes, + parameter_bytes.as_slice_mut(), ¶meter_accounts, invoke_context, ) { @@ -857,7 +858,7 @@ impl Executor for BpfExecutor { deserialize_parameters( loader_id, parameter_accounts, - ¶meter_bytes, + parameter_bytes.as_slice(), invoke_context.is_feature_active(&skip_ro_deserialization::id()), )?; deserialize_time.stop(); diff --git a/programs/bpf_loader/src/serialization.rs b/programs/bpf_loader/src/serialization.rs index 1549ad0930..6ee0ccf37c 100644 --- a/programs/bpf_loader/src/serialization.rs +++ b/programs/bpf_loader/src/serialization.rs @@ -1,4 +1,5 @@ use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; +use solana_rbpf::{aligned_memory::AlignedMemory, ebpf::HOST_ALIGN}; use solana_sdk::{ account::{ReadableAccount, WritableAccount}, bpf_loader_deprecated, @@ -27,7 +28,7 @@ pub fn serialize_parameters( program_id: &Pubkey, keyed_accounts: &[KeyedAccount], data: &[u8], -) -> Result, InstructionError> { +) -> Result { if *loader_id == bpf_loader_deprecated::id() { serialize_parameters_unaligned(program_id, keyed_accounts, data) } else { @@ -69,7 +70,7 @@ pub fn serialize_parameters_unaligned( program_id: &Pubkey, keyed_accounts: &[KeyedAccount], instruction_data: &[u8], -) -> Result, InstructionError> { +) -> Result { // Calculate size in order to alloc once let mut size = size_of::(); for (i, keyed_account) in keyed_accounts.iter().enumerate() { @@ -82,7 +83,7 @@ pub fn serialize_parameters_unaligned( size += size_of::() // instruction data len + instruction_data.len() // instruction data + size_of::(); // program id - let mut v: Vec = Vec::with_capacity(size); + let mut v = AlignedMemory::new(size, HOST_ALIGN); v.write_u64::(keyed_accounts.len() as u64) .map_err(|_| InstructionError::InvalidArgument)?; @@ -182,7 +183,7 @@ pub fn serialize_parameters_aligned( program_id: &Pubkey, keyed_accounts: &[KeyedAccount], instruction_data: &[u8], -) -> Result, InstructionError> { +) -> Result { // Calculate size in order to alloc once let mut size = size_of::(); for (i, keyed_account) in keyed_accounts.iter().enumerate() { @@ -197,14 +198,11 @@ pub fn serialize_parameters_aligned( size += size_of::() // data len + instruction_data.len() + size_of::(); // program id; - let mut v: Vec = Vec::with_capacity(size); + let mut v = AlignedMemory::new(size, HOST_ALIGN); // Serialize into the buffer v.write_u64::(keyed_accounts.len() as u64) .map_err(|_| InstructionError::InvalidArgument)?; - if v.as_ptr().align_offset(align_of::()) != 0 { - panic!(); - } for (i, keyed_account) in keyed_accounts.iter().enumerate() { let (is_dup, position) = is_dup(&keyed_accounts[..i], keyed_account); if is_dup { @@ -233,12 +231,12 @@ pub fn serialize_parameters_aligned( .map_err(|_| InstructionError::InvalidArgument)?; v.write_all(&keyed_account.try_account_ref()?.data()) .map_err(|_| InstructionError::InvalidArgument)?; - v.resize( - v.len() - + MAX_PERMITTED_DATA_INCREASE - + (v.len() as *const u8).align_offset(align_of::()), + v.fill( + MAX_PERMITTED_DATA_INCREASE + + (v.write_index() as *const u8).align_offset(align_of::()), 0, - ); + ) + .map_err(|_| InstructionError::InvalidArgument)?; v.write_u64::(keyed_account.rent_epoch()? as u64) .map_err(|_| InstructionError::InvalidArgument)?; } @@ -414,7 +412,8 @@ mod tests { .unwrap(); let (de_program_id, de_accounts, de_instruction_data) = - unsafe { deserialize(&mut serialized[0] as *mut u8) }; + unsafe { deserialize(&mut serialized.as_slice_mut()[0] as *mut u8) }; + assert_eq!(&program_id, de_program_id); assert_eq!(instruction_data, de_instruction_data); assert_eq!( @@ -457,7 +456,13 @@ mod tests { } }) .collect(); - deserialize_parameters(&bpf_loader::id(), &de_keyed_accounts, &serialized, true).unwrap(); + deserialize_parameters( + &bpf_loader::id(), + &de_keyed_accounts, + serialized.as_slice(), + true, + ) + .unwrap(); for ((account, de_keyed_account), key) in accounts.iter().zip(de_keyed_accounts).zip(keys.clone()) { @@ -484,7 +489,7 @@ mod tests { .unwrap(); let (de_program_id, de_accounts, de_instruction_data) = - unsafe { deserialize_unaligned(&mut serialized[0] as *mut u8) }; + unsafe { deserialize_unaligned(&mut serialized.as_slice_mut()[0] as *mut u8) }; assert_eq!(&program_id, de_program_id); assert_eq!(instruction_data, de_instruction_data); for ((account, account_info), key) in accounts.iter().zip(de_accounts).zip(keys.clone()) { @@ -513,7 +518,7 @@ mod tests { deserialize_parameters( &bpf_loader_deprecated::id(), &de_keyed_accounts, - &serialized, + serialized.as_slice(), true, ) .unwrap(); diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 989247ae59..63c55dfaa7 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -2,6 +2,7 @@ use crate::{alloc, BpfError}; use alloc::Alloc; use curve25519_dalek::{ristretto::RistrettoPoint, scalar::Scalar}; use solana_rbpf::{ + aligned_memory::AlignedMemory, ebpf::MM_HEAP_START, error::EbpfError, memory_region::{AccessType, MemoryMapping}, @@ -20,7 +21,7 @@ use solana_sdk::{ epoch_schedule::EpochSchedule, feature_set::{ cpi_data_cost, cpi_share_ro_and_exec_accounts, demote_sysvar_write_locks, - ristretto_mul_syscall_enabled, sysvar_via_syscall, + enforce_aligned_host_addrs, ristretto_mul_syscall_enabled, sysvar_via_syscall, }, hash::{Hasher, HASH_BYTES}, ic_msg, @@ -171,9 +172,11 @@ pub fn bind_syscall_context_objects<'a>( vm: &mut EbpfVm<'a, BpfError, crate::ThisInstructionMeter>, callers_keyed_accounts: &'a [KeyedAccount<'a>], invoke_context: &'a mut dyn InvokeContext, - heap: Vec, + heap: AlignedMemory, ) -> Result<(), EbpfError> { let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); + let enforce_aligned_host_addrs = + invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); // Syscall functions common across languages @@ -182,6 +185,7 @@ pub fn bind_syscall_context_objects<'a>( Box::new(SyscallPanic { compute_meter: invoke_context.get_compute_meter(), loader_id, + enforce_aligned_host_addrs, }), None, )?; @@ -190,6 +194,7 @@ pub fn bind_syscall_context_objects<'a>( compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), loader_id, + enforce_aligned_host_addrs, }), None, )?; @@ -217,6 +222,7 @@ pub fn bind_syscall_context_objects<'a>( compute_meter: invoke_context.get_compute_meter(), logger: invoke_context.get_logger(), loader_id, + enforce_aligned_host_addrs, }), None, )?; @@ -226,6 +232,7 @@ pub fn bind_syscall_context_objects<'a>( cost: bpf_compute_budget.create_program_address_units, compute_meter: invoke_context.get_compute_meter(), loader_id, + enforce_aligned_host_addrs, }), None, )?; @@ -235,6 +242,7 @@ pub fn bind_syscall_context_objects<'a>( cost: bpf_compute_budget.create_program_address_units, compute_meter: invoke_context.get_compute_meter(), loader_id, + enforce_aligned_host_addrs, }), None, )?; @@ -245,6 +253,7 @@ pub fn bind_syscall_context_objects<'a>( sha256_byte_cost: bpf_compute_budget.sha256_byte_cost, compute_meter: invoke_context.get_compute_meter(), loader_id, + enforce_aligned_host_addrs, }), None, )?; @@ -256,6 +265,7 @@ pub fn bind_syscall_context_objects<'a>( cost: 0, compute_meter: invoke_context.get_compute_meter(), loader_id, + enforce_aligned_host_addrs, }), ); @@ -341,32 +351,53 @@ fn translate_type_inner<'a, T>( access_type: AccessType, vm_addr: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<&'a mut T, EbpfError> { - if loader_id != &bpf_loader_deprecated::id() - && (vm_addr as u64 as *mut T).align_offset(align_of::()) != 0 + if !enforce_aligned_host_addrs + && loader_id != &bpf_loader_deprecated::id() + && (vm_addr as *mut T).align_offset(align_of::()) != 0 { - Err(SyscallError::UnalignedPointer.into()) - } else { - unsafe { - translate(memory_mapping, access_type, vm_addr, size_of::() as u64) - .map(|value| &mut *(value as *mut T)) - } + return Err(SyscallError::UnalignedPointer.into()); } + + let host_addr = translate(memory_mapping, access_type, vm_addr, size_of::() as u64)?; + + if enforce_aligned_host_addrs + && loader_id != &bpf_loader_deprecated::id() + && (host_addr as *mut T).align_offset(align_of::()) != 0 + { + return Err(SyscallError::UnalignedPointer.into()); + } + Ok(unsafe { &mut *(host_addr as *mut T) }) } fn translate_type_mut<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<&'a mut T, EbpfError> { - translate_type_inner::(memory_mapping, AccessType::Store, vm_addr, loader_id) + translate_type_inner::( + memory_mapping, + AccessType::Store, + vm_addr, + loader_id, + enforce_aligned_host_addrs, + ) } fn translate_type<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<&'a T, EbpfError> { - translate_type_inner::(memory_mapping, AccessType::Load, vm_addr, loader_id) - .map(|value| &*value) + translate_type_inner::( + memory_mapping, + AccessType::Load, + vm_addr, + loader_id, + enforce_aligned_host_addrs, + ) + .map(|value| &*value) } fn translate_slice_inner<'a, T>( @@ -375,41 +406,65 @@ fn translate_slice_inner<'a, T>( vm_addr: u64, len: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<&'a mut [T], EbpfError> { - if loader_id != &bpf_loader_deprecated::id() + if !enforce_aligned_host_addrs + && loader_id != &bpf_loader_deprecated::id() && (vm_addr as u64 as *mut T).align_offset(align_of::()) != 0 { - Err(SyscallError::UnalignedPointer.into()) - } else if len == 0 { - Ok(&mut []) - } else { - match translate( - memory_mapping, - access_type, - vm_addr, - len.saturating_mul(size_of::() as u64), - ) { - Ok(value) => Ok(unsafe { from_raw_parts_mut(value as *mut T, len as usize) }), - Err(e) => Err(e), - } + return Err(SyscallError::UnalignedPointer.into()); } + if len == 0 { + return Ok(&mut []); + } + + let host_addr = translate( + memory_mapping, + access_type, + vm_addr, + len.saturating_mul(size_of::() as u64), + )?; + + if enforce_aligned_host_addrs + && loader_id != &bpf_loader_deprecated::id() + && (host_addr as *mut T).align_offset(align_of::()) != 0 + { + return Err(SyscallError::UnalignedPointer.into()); + } + Ok(unsafe { from_raw_parts_mut(host_addr as *mut T, len as usize) }) } fn translate_slice_mut<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, len: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<&'a mut [T], EbpfError> { - translate_slice_inner::(memory_mapping, AccessType::Store, vm_addr, len, loader_id) + translate_slice_inner::( + memory_mapping, + AccessType::Store, + vm_addr, + len, + loader_id, + enforce_aligned_host_addrs, + ) } fn translate_slice<'a, T>( memory_mapping: &MemoryMapping, vm_addr: u64, len: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<&'a [T], EbpfError> { - translate_slice_inner::(memory_mapping, AccessType::Load, vm_addr, len, loader_id) - .map(|value| &*value) + translate_slice_inner::( + memory_mapping, + AccessType::Load, + vm_addr, + len, + loader_id, + enforce_aligned_host_addrs, + ) + .map(|value| &*value) } /// Take a virtual pointer to a string (points to BPF VM memory space), translate it @@ -419,9 +474,16 @@ fn translate_string_and_do( addr: u64, len: u64, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, work: &mut dyn FnMut(&str) -> Result>, ) -> Result> { - let buf = translate_slice::(memory_mapping, addr, len, loader_id)?; + let buf = translate_slice::( + memory_mapping, + addr, + len, + loader_id, + enforce_aligned_host_addrs, + )?; let i = match buf.iter().position(|byte| *byte == 0) { Some(i) => i, None => len as usize, @@ -458,6 +520,7 @@ impl SyscallObject for SyscallAbort { pub struct SyscallPanic<'a> { compute_meter: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallPanic<'a> { fn call( @@ -476,6 +539,7 @@ impl<'a> SyscallObject for SyscallPanic<'a> { file, len, &self.loader_id, + self.enforce_aligned_host_addrs, &mut |string: &str| Err(SyscallError::Panic(string.to_string(), line, column).into()), ); } @@ -486,6 +550,7 @@ pub struct SyscallLog<'a> { compute_meter: Rc>, logger: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallLog<'a> { fn call( @@ -505,6 +570,7 @@ impl<'a> SyscallObject for SyscallLog<'a> { addr, len, &self.loader_id, + self.enforce_aligned_host_addrs, &mut |string: &str| { stable_log::program_log(&self.logger, string); Ok(0) @@ -585,6 +651,7 @@ pub struct SyscallLogPubkey<'a> { compute_meter: Rc>, logger: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallLogPubkey<'a> { fn call( @@ -599,7 +666,12 @@ impl<'a> SyscallObject for SyscallLogPubkey<'a> { ) { question_mark!(self.compute_meter.consume(self.cost), result); let pubkey = question_mark!( - translate_type::(memory_mapping, pubkey_addr, self.loader_id), + translate_type::( + memory_mapping, + pubkey_addr, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); stable_log::program_log(&self.logger, &pubkey.to_string()); @@ -658,9 +730,15 @@ fn translate_program_address_inputs<'a>( program_id_addr: u64, memory_mapping: &MemoryMapping, loader_id: &Pubkey, + enforce_aligned_host_addrs: bool, ) -> Result<(Vec<&'a [u8]>, &'a Pubkey), EbpfError> { - let untranslated_seeds = - translate_slice::<&[&u8]>(memory_mapping, seeds_addr, seeds_len, loader_id)?; + let untranslated_seeds = translate_slice::<&[&u8]>( + memory_mapping, + seeds_addr, + seeds_len, + loader_id, + enforce_aligned_host_addrs, + )?; if untranslated_seeds.len() > MAX_SEEDS { return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into()); } @@ -672,10 +750,16 @@ fn translate_program_address_inputs<'a>( untranslated_seed.as_ptr() as *const _ as u64, untranslated_seed.len() as u64, loader_id, + enforce_aligned_host_addrs, ) }) .collect::, EbpfError>>()?; - let program_id = translate_type::(memory_mapping, program_id_addr, loader_id)?; + let program_id = translate_type::( + memory_mapping, + program_id_addr, + loader_id, + enforce_aligned_host_addrs, + )?; Ok((seeds, program_id)) } @@ -684,6 +768,7 @@ struct SyscallCreateProgramAddress<'a> { cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallCreateProgramAddress<'a> { fn call( @@ -703,6 +788,7 @@ impl<'a> SyscallObject for SyscallCreateProgramAddress<'a> { program_id_addr, memory_mapping, self.loader_id, + self.enforce_aligned_host_addrs, ), result ); @@ -716,7 +802,13 @@ impl<'a> SyscallObject for SyscallCreateProgramAddress<'a> { } }; let address = question_mark!( - translate_slice_mut::(memory_mapping, address_addr, 32, self.loader_id), + translate_slice_mut::( + memory_mapping, + address_addr, + 32, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); address.copy_from_slice(new_address.as_ref()); @@ -729,6 +821,7 @@ struct SyscallTryFindProgramAddress<'a> { cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallTryFindProgramAddress<'a> { fn call( @@ -748,6 +841,7 @@ impl<'a> SyscallObject for SyscallTryFindProgramAddress<'a> { program_id_addr, memory_mapping, self.loader_id, + self.enforce_aligned_host_addrs, ), result ); @@ -763,11 +857,22 @@ impl<'a> SyscallObject for SyscallTryFindProgramAddress<'a> { Pubkey::create_program_address(&seeds_with_bump, program_id) { let bump_seed_ref = question_mark!( - translate_type_mut::(memory_mapping, bump_seed_addr, self.loader_id), + translate_type_mut::( + memory_mapping, + bump_seed_addr, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); let address = question_mark!( - translate_slice_mut::(memory_mapping, address_addr, 32, self.loader_id), + translate_slice_mut::( + memory_mapping, + address_addr, + 32, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); *bump_seed_ref = bump_seed[0]; @@ -788,6 +893,7 @@ pub struct SyscallSha256<'a> { sha256_byte_cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallSha256<'a> { fn call( @@ -806,14 +912,21 @@ impl<'a> SyscallObject for SyscallSha256<'a> { memory_mapping, result_addr, HASH_BYTES as u64, - self.loader_id + self.loader_id, + self.enforce_aligned_host_addrs, ), result ); let mut hasher = Hasher::default(); if vals_len > 0 { let vals = question_mark!( - translate_slice::<&[u8]>(memory_mapping, vals_addr, vals_len, self.loader_id), + translate_slice::<&[u8]>( + memory_mapping, + vals_addr, + vals_len, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); for val in vals.iter() { @@ -822,7 +935,8 @@ impl<'a> SyscallObject for SyscallSha256<'a> { memory_mapping, val.as_ptr() as u64, val.len() as u64, - self.loader_id + self.loader_id, + self.enforce_aligned_host_addrs, ), result ); @@ -844,6 +958,7 @@ pub struct SyscallRistrettoMul<'a> { cost: u64, compute_meter: Rc>, loader_id: &'a Pubkey, + enforce_aligned_host_addrs: bool, } impl<'a> SyscallObject for SyscallRistrettoMul<'a> { fn call( @@ -859,15 +974,30 @@ impl<'a> SyscallObject for SyscallRistrettoMul<'a> { question_mark!(self.compute_meter.consume(self.cost), result); let point = question_mark!( - translate_type::(memory_mapping, point_addr, self.loader_id), + translate_type::( + memory_mapping, + point_addr, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); let scalar = question_mark!( - translate_type::(memory_mapping, scalar_addr, self.loader_id), + translate_type::( + memory_mapping, + scalar_addr, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); let output = question_mark!( - translate_type_mut::(memory_mapping, result_addr, self.loader_id), + translate_type_mut::( + memory_mapping, + result_addr, + self.loader_id, + self.enforce_aligned_host_addrs, + ), result ); *output = point * scalar; @@ -890,7 +1020,12 @@ fn get_sysvar( invoke_context.get_compute_meter().consume( invoke_context.get_bpf_compute_budget().sysvar_base_cost + size_of::() as u64, )?; - let var = translate_type_mut::(memory_mapping, var_addr, loader_id)?; + let var = translate_type_mut::( + memory_mapping, + var_addr, + loader_id, + invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()), + )?; let sysvar_data = invoke_context.get_sysvar_data(id).ok_or_else(|| { ic_msg!(invoke_context, "Unable to get Sysvar {}", id); @@ -1034,6 +1169,7 @@ trait SyscallInvokeSigned<'a> { &self, addr: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result>; fn translate_accounts( &self, @@ -1050,6 +1186,7 @@ trait SyscallInvokeSigned<'a> { signers_seeds_addr: u64, signers_seeds_len: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result, EbpfError>; } @@ -1077,8 +1214,14 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { &self, addr: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result> { - let ix = translate_type::(memory_mapping, addr, self.loader_id)?; + let ix = translate_type::( + memory_mapping, + addr, + self.loader_id, + enforce_aligned_host_addrs, + )?; check_instruction_size( ix.accounts.len(), @@ -1091,6 +1234,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { ix.accounts.as_ptr() as u64, ix.accounts.len() as u64, self.loader_id, + enforce_aligned_host_addrs, )? .to_vec(); let data = translate_slice::( @@ -1098,6 +1242,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { ix.data.as_ptr() as u64, ix.data.len() as u64, self.loader_id, + enforce_aligned_host_addrs, )? .to_vec(); Ok(Instruction { @@ -1117,12 +1262,15 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { memory_mapping: &MemoryMapping, ) -> Result, EbpfError> { let invoke_context = self.invoke_context.borrow(); + let enforce_aligned_host_addrs = + invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); let account_infos = translate_slice::( memory_mapping, account_infos_addr, account_infos_len, self.loader_id, + enforce_aligned_host_addrs, )?; check_account_infos(account_infos.len(), &invoke_context)?; let account_info_keys = account_infos @@ -1132,6 +1280,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { memory_mapping, account_info.key as *const _ as u64, self.loader_id, + enforce_aligned_host_addrs, ) }) .collect::, EbpfError>>()?; @@ -1146,13 +1295,20 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { memory_mapping, account_info.lamports.as_ptr() as u64, self.loader_id, + enforce_aligned_host_addrs, )?; - translate_type_mut::(memory_mapping, *ptr, self.loader_id)? + translate_type_mut::( + memory_mapping, + *ptr, + self.loader_id, + enforce_aligned_host_addrs, + )? }; let owner = translate_type_mut::( memory_mapping, account_info.owner as *const _ as u64, self.loader_id, + enforce_aligned_host_addrs, )?; let (data, vm_data_addr, ref_to_len_in_vm, serialized_len_ptr) = { @@ -1161,6 +1317,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { memory_mapping, account_info.data.as_ptr() as *const _ as u64, self.loader_id, + enforce_aligned_host_addrs, )?; if invoke_context.is_feature_active(&cpi_data_cost::id()) { @@ -1182,6 +1339,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { memory_mapping, ref_of_len_in_input_buffer as *const _ as u64, self.loader_id, + enforce_aligned_host_addrs, )?; let vm_data_addr = data.as_ptr() as u64; ( @@ -1190,6 +1348,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { vm_data_addr, data.len() as u64, self.loader_id, + enforce_aligned_host_addrs, )?, vm_data_addr, ref_to_len_in_vm, @@ -1233,6 +1392,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { signers_seeds_addr: u64, signers_seeds_len: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result, EbpfError> { let mut signers = Vec::new(); if signers_seeds_len > 0 { @@ -1241,6 +1401,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { signers_seeds_addr, signers_seeds_len, self.loader_id, + enforce_aligned_host_addrs, )?; if signers_seeds.len() > MAX_SIGNERS { return Err(SyscallError::TooManySigners.into()); @@ -1251,6 +1412,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { signer_seeds.as_ptr() as *const _ as u64, signer_seeds.len() as u64, self.loader_id, + enforce_aligned_host_addrs, )?; if untranslated_seeds.len() > MAX_SEEDS { return Err(SyscallError::InstructionError( @@ -1266,6 +1428,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { untranslated_seed.as_ptr() as *const _ as u64, untranslated_seed.len() as u64, self.loader_id, + enforce_aligned_host_addrs, ) }) .collect::, EbpfError>>()?; @@ -1374,34 +1537,50 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { &self, addr: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result> { - let ix_c = translate_type::(memory_mapping, addr, self.loader_id)?; + let ix_c = translate_type::( + memory_mapping, + addr, + self.loader_id, + enforce_aligned_host_addrs, + )?; check_instruction_size( ix_c.accounts_len, ix_c.data_len, &self.invoke_context.borrow(), )?; - let program_id = - translate_type::(memory_mapping, ix_c.program_id_addr, self.loader_id)?; + let program_id = translate_type::( + memory_mapping, + ix_c.program_id_addr, + self.loader_id, + enforce_aligned_host_addrs, + )?; let meta_cs = translate_slice::( memory_mapping, ix_c.accounts_addr, ix_c.accounts_len as u64, self.loader_id, + enforce_aligned_host_addrs, )?; let data = translate_slice::( memory_mapping, ix_c.data_addr, ix_c.data_len as u64, self.loader_id, + enforce_aligned_host_addrs, )? .to_vec(); let accounts = meta_cs .iter() .map(|meta_c| { - let pubkey = - translate_type::(memory_mapping, meta_c.pubkey_addr, self.loader_id)?; + let pubkey = translate_type::( + memory_mapping, + meta_c.pubkey_addr, + self.loader_id, + enforce_aligned_host_addrs, + )?; Ok(AccountMeta { pubkey: *pubkey, is_signer: meta_c.is_signer, @@ -1427,18 +1606,26 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { memory_mapping: &MemoryMapping, ) -> Result, EbpfError> { let invoke_context = self.invoke_context.borrow(); + let enforce_aligned_host_addrs = + invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); let account_infos = translate_slice::( memory_mapping, account_infos_addr, account_infos_len, self.loader_id, + enforce_aligned_host_addrs, )?; check_account_infos(account_infos.len(), &invoke_context)?; let account_info_keys = account_infos .iter() .map(|account_info| { - translate_type::(memory_mapping, account_info.key_addr, self.loader_id) + translate_type::( + memory_mapping, + account_info.key_addr, + self.loader_id, + enforce_aligned_host_addrs, + ) }) .collect::, EbpfError>>()?; @@ -1450,11 +1637,13 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { memory_mapping, account_info.lamports_addr, self.loader_id, + enforce_aligned_host_addrs, )?; let owner = translate_type_mut::( memory_mapping, account_info.owner_addr, self.loader_id, + enforce_aligned_host_addrs, )?; let vm_data_addr = account_info.data_addr; @@ -1470,6 +1659,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { vm_data_addr, account_info.data_len, self.loader_id, + enforce_aligned_host_addrs, )?; let first_info_addr = &account_infos[0] as *const _ as u64; @@ -1489,6 +1679,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { memory_mapping, ref_of_len_in_input_buffer as *const _ as u64, self.loader_id, + enforce_aligned_host_addrs, )?; Ok(( @@ -1527,6 +1718,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { signers_seeds_addr: u64, signers_seeds_len: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result, EbpfError> { if signers_seeds_len > 0 { let signers_seeds = translate_slice::( @@ -1534,6 +1726,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { signers_seeds_addr, signers_seeds_len, self.loader_id, + enforce_aligned_host_addrs, )?; if signers_seeds.len() > MAX_SIGNERS { return Err(SyscallError::TooManySigners.into()); @@ -1546,6 +1739,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { signer_seeds.addr, signer_seeds.len, self.loader_id, + enforce_aligned_host_addrs, )?; if seeds.len() > MAX_SEEDS { return Err(SyscallError::InstructionError( @@ -1561,6 +1755,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { seed.addr, seed.len, self.loader_id, + enforce_aligned_host_addrs, ) }) .collect::, EbpfError>>()?; @@ -1764,18 +1959,26 @@ fn call<'a>( .get_compute_meter() .consume(invoke_context.get_bpf_compute_budget().invoke_units)?; + let enforce_aligned_host_addrs = + invoke_context.is_feature_active(&enforce_aligned_host_addrs::id()); + let caller_program_id = invoke_context .get_caller() .map_err(SyscallError::InstructionError)?; // Translate and verify caller's data - let instruction = syscall.translate_instruction(instruction_addr, &memory_mapping)?; + let instruction = syscall.translate_instruction( + instruction_addr, + &memory_mapping, + enforce_aligned_host_addrs, + )?; let signers = syscall.translate_signers( caller_program_id, signers_seeds_addr, signers_seeds_len, memory_mapping, + enforce_aligned_host_addrs, )?; let keyed_account_refs = syscall .get_callers_keyed_accounts() @@ -1917,7 +2120,9 @@ fn call<'a>( #[cfg(test)] mod tests { use super::*; - use solana_rbpf::{memory_region::MemoryRegion, user_error::UserError, vm::Config}; + use solana_rbpf::{ + ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config, + }; use solana_sdk::{ bpf_loader, fee_calculator::FeeCalculator, @@ -1999,7 +2204,7 @@ mod tests { ) .unwrap(); let translated_pubkey = - translate_type::(&memory_mapping, 100, &bpf_loader::id()).unwrap(); + translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).unwrap(); assert_eq!(pubkey, *translated_pubkey); // Instruction @@ -2009,7 +2214,7 @@ mod tests { vec![AccountMeta::new(solana_sdk::pubkey::new_rand(), false)], ); let addr = &instruction as *const _ as u64; - let memory_mapping = MemoryMapping::new::( + let mut memory_mapping = MemoryMapping::new::( vec![MemoryRegion { host_addr: addr, vm_addr: 96, @@ -2021,12 +2226,12 @@ mod tests { ) .unwrap(); let translated_instruction = - translate_type::(&memory_mapping, 96, &bpf_loader::id()).unwrap(); + translate_type::(&memory_mapping, 96, &bpf_loader::id(), true).unwrap(); assert_eq!(instruction, *translated_instruction); - // TODO: Reenable when solana_rbpf is bumped to "0.2.8" or higher - // Text search anchor so that it is easier to find: solana_rbpf = "=0.2.7" - // memory_mapping.resize_region::(0, 1).unwrap(); - // assert!(translate_type::(&memory_mapping, 100, &bpf_loader::id()).is_err()); + memory_mapping.resize_region::(0, 1).unwrap(); + assert!( + translate_type::(&memory_mapping, 100, &bpf_loader::id(), true).is_err() + ); } #[test] @@ -2047,9 +2252,14 @@ mod tests { &DEFAULT_CONFIG, ) .unwrap(); - let translated_data = - translate_slice::(&memory_mapping, data.as_ptr() as u64, 0, &bpf_loader::id()) - .unwrap(); + let translated_data = translate_slice::( + &memory_mapping, + data.as_ptr() as u64, + 0, + &bpf_loader::id(), + true, + ) + .unwrap(); assert_eq!(data, translated_data); assert_eq!(0, translated_data.len()); @@ -2067,9 +2277,14 @@ mod tests { &DEFAULT_CONFIG, ) .unwrap(); - let translated_data = - translate_slice::(&memory_mapping, 100, data.len() as u64, &bpf_loader::id()) - .unwrap(); + let translated_data = translate_slice::( + &memory_mapping, + 100, + data.len() as u64, + &bpf_loader::id(), + true, + ) + .unwrap(); assert_eq!(data, translated_data); data[0] = 10; assert_eq!(data, translated_data); @@ -2077,7 +2292,8 @@ mod tests { &memory_mapping, data.as_ptr() as u64, u64::MAX, - &bpf_loader::id() + &bpf_loader::id(), + true, ) .is_err()); @@ -2085,7 +2301,8 @@ mod tests { &memory_mapping, 100 - 1, data.len() as u64, - &bpf_loader::id() + &bpf_loader::id(), + true, ) .is_err()); @@ -2103,13 +2320,21 @@ mod tests { &DEFAULT_CONFIG, ) .unwrap(); - let translated_data = - translate_slice::(&memory_mapping, 96, data.len() as u64, &bpf_loader::id()) - .unwrap(); + let translated_data = translate_slice::( + &memory_mapping, + 96, + data.len() as u64, + &bpf_loader::id(), + true, + ) + .unwrap(); assert_eq!(data, translated_data); data[0] = 10; assert_eq!(data, translated_data); - assert!(translate_slice::(&memory_mapping, 96, u64::MAX, &bpf_loader::id()).is_err()); + assert!( + translate_slice::(&memory_mapping, 96, u64::MAX, &bpf_loader::id(), true,) + .is_err() + ); // Pubkeys let mut data = vec![solana_sdk::pubkey::new_rand(); 5]; @@ -2125,9 +2350,14 @@ mod tests { &DEFAULT_CONFIG, ) .unwrap(); - let translated_data = - translate_slice::(&memory_mapping, 100, data.len() as u64, &bpf_loader::id()) - .unwrap(); + let translated_data = translate_slice::( + &memory_mapping, + 100, + data.len() as u64, + &bpf_loader::id(), + true, + ) + .unwrap(); assert_eq!(data, translated_data); data[0] = solana_sdk::pubkey::new_rand(); // Both should point to same place assert_eq!(data, translated_data); @@ -2155,6 +2385,7 @@ mod tests { 100, string.len() as u64, &bpf_loader::id(), + true, &mut |string: &str| { assert_eq!(string, "Gaggablaghblagh!"); Ok(42) @@ -2208,6 +2439,7 @@ mod tests { let mut syscall_panic = SyscallPanic { compute_meter, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let mut result: Result> = Ok(0); syscall_panic.call( @@ -2233,6 +2465,7 @@ mod tests { let mut syscall_panic = SyscallPanic { compute_meter, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let mut result: Result> = Ok(0); syscall_panic.call( @@ -2261,6 +2494,7 @@ mod tests { compute_meter, logger, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let memory_mapping = MemoryMapping::new::( vec![MemoryRegion { @@ -2330,6 +2564,7 @@ mod tests { compute_meter, logger, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let mut result: Result> = Ok(0); syscall_sol_log.call( @@ -2399,6 +2634,7 @@ mod tests { compute_meter, logger, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let memory_mapping = MemoryMapping::new::( vec![MemoryRegion { @@ -2445,9 +2681,14 @@ mod tests { fn test_syscall_sol_alloc_free() { // large alloc { - let heap = vec![0_u8; 100]; + let heap = AlignedMemory::new(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice(&heap, MM_HEAP_START, 0, true)], + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], &DEFAULT_CONFIG, ) .unwrap(); @@ -2467,9 +2708,14 @@ mod tests { } // many small unaligned allocs { - let heap = vec![0_u8; 100]; + let heap = AlignedMemory::new(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice(&heap, MM_HEAP_START, 0, true)], + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], &DEFAULT_CONFIG, ) .unwrap(); @@ -2488,9 +2734,14 @@ mod tests { } // many small aligned allocs { - let heap = vec![0_u8; 100]; + let heap = AlignedMemory::new(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice(&heap, MM_HEAP_START, 0, true)], + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], &DEFAULT_CONFIG, ) .unwrap(); @@ -2510,9 +2761,14 @@ mod tests { // aligned allocs fn check_alignment() { - let heap = vec![0_u8; 100]; + let heap = AlignedMemory::new(100, HOST_ALIGN); let memory_mapping = MemoryMapping::new::( - vec![MemoryRegion::new_from_slice(&heap, MM_HEAP_START, 0, true)], + vec![MemoryRegion::new_from_slice( + heap.as_slice(), + MM_HEAP_START, + 0, + true, + )], &DEFAULT_CONFIG, ) .unwrap(); @@ -2606,6 +2862,7 @@ mod tests { sha256_byte_cost: 2, compute_meter, loader_id: &bpf_loader_deprecated::id(), + enforce_aligned_host_addrs: true, }; let mut result: Result> = Ok(0); diff --git a/sdk/src/feature_set.rs b/sdk/src/feature_set.rs index e831de9468..3ccac9de37 100644 --- a/sdk/src/feature_set.rs +++ b/sdk/src/feature_set.rs @@ -135,6 +135,10 @@ pub mod check_duplicates_by_hash { solana_sdk::declare_id!("8ZqTSYHgzyaYCcXJPMViRy6afCFSgNvYooPDeVdyj5GC"); } +pub mod enforce_aligned_host_addrs { + solana_sdk::declare_id!("6Qob9Z4RwGdf599FDVCqsjuKjR8ZFR3oVs2ByRLWBsua"); +} + lazy_static! { /// Map of feature identifiers to user-visible description pub static ref FEATURE_NAMES: HashMap = [ @@ -156,8 +160,8 @@ lazy_static! { (turbine_retransmit_peers_patch::id(), "turbine retransmit peers patch #14631"), (require_custodian_for_locked_stake_authorize::id(), "require custodian to authorize withdrawer change for locked stake"), (spl_token_v2_self_transfer_fix::id(), "spl-token self-transfer fix"), - (full_inflation::mainnet::certusone::enable::id(), "Full inflation enabled by Certus One"), - (full_inflation::mainnet::certusone::vote::id(), "Community vote allowing Certus One to enable full inflation"), + (full_inflation::mainnet::certusone::enable::id(), "full inflation enabled by Certus One"), + (full_inflation::mainnet::certusone::vote::id(), "community vote allowing Certus One to enable full inflation"), (warp_timestamp_again::id(), "warp timestamp again, adjust bounding to 25% fast 80% slow #15204"), (check_init_vote_data::id(), "check initialized Vote data"), (check_program_owner::id(), "limit programs to operating on accounts owned by itself"), @@ -167,8 +171,9 @@ lazy_static! { (cpi_data_cost::id(), "charge the compute budget for data passed via CPI"), (upgradeable_close_instruction::id(), "close upgradeable buffer accounts"), (demote_sysvar_write_locks::id(), "demote builtins and sysvar write locks to readonly #15497"), - (sysvar_via_syscall::id(), "Provide sysvars via syscalls"), + (sysvar_via_syscall::id(), "provide sysvars via syscalls"), (check_duplicates_by_hash::id(), "use transaction message hash for duplicate check"), + (enforce_aligned_host_addrs::id(), "enforce aligned host addresses"), /*************** ADD NEW FEATURES HERE ***************/ ] .iter()