diff --git a/Cargo.lock b/Cargo.lock index b4baa51496..ef0ee87b43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5471,9 +5471,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 5e4bba6259..cf8592507e 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -38,7 +38,7 @@ solana-config-program = { path = "../programs/config", version = "=1.7.0" } solana-faucet = { path = "../faucet", version = "=1.7.0" } solana-logger = { path = "../logger", version = "=1.7.0" } solana-net-utils = { path = "../net-utils", version = "=1.7.0" } -solana_rbpf = "=0.2.7" +solana_rbpf = "=0.2.8" solana-remote-wallet = { path = "../remote-wallet", version = "=1.7.0" } solana-sdk = { path = "../sdk", version = "=1.7.0" } solana-stake-program = { path = "../programs/stake", version = "=1.7.0" } diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 6f14cbe75e..2c0fdbfe0f 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -3595,9 +3595,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 ac20026442..f1d458b00f 100644 --- a/programs/bpf/Cargo.toml +++ b/programs/bpf/Cargo.toml @@ -29,7 +29,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.7.0" } solana-cli-output = { path = "../../cli-output", version = "=1.7.0" } solana-logger = { path = "../../logger", version = "=1.7.0" } solana-measure = { path = "../../measure", version = "=1.7.0" } -solana_rbpf = "=0.2.7" +solana_rbpf = "=0.2.8" solana-runtime = { path = "../../runtime", version = "=1.7.0" } solana-sdk = { path = "../../sdk", version = "=1.7.0" } solana-transaction-status = { path = "../../transaction-status", version = "=1.7.0" } diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index d4cf722fa3..5a79157add 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 _ = - >::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 = - >::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(); @@ -223,7 +226,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { let elf = load_elf("tuner").unwrap(); let mut 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(); @@ -231,7 +234,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, ) .unwrap(); diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 406697ad19..c5f814c90c 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -217,7 +217,7 @@ fn run_program( let mut vm = create_vm( &loader_id, executable.as_ref(), - &mut parameter_bytes, + parameter_bytes.as_slice_mut(), &mut invoke_context, ) .unwrap(); @@ -256,7 +256,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 80d5c38f0a..a6ba4c649c 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.7.0" } solana-runtime = { path = "../../runtime", version = "=1.7.0" } solana-sdk = { path = "../../sdk", version = "=1.7.0" } -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 fab9defc98..4706c207fe 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}, @@ -147,8 +148,8 @@ pub fn create_vm<'a>( parameter_bytes: &mut [u8], 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, &mut vm, invoke_context, heap)?; Ok(vm) @@ -759,7 +760,7 @@ impl Executor for BpfExecutor { let mut vm = match create_vm( loader_id, self.executable.as_ref(), - &mut parameter_bytes, + parameter_bytes.as_slice_mut(), invoke_context, ) { Ok(info) => info, @@ -823,7 +824,7 @@ impl Executor for BpfExecutor { deserialize_parameters( loader_id, keyed_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 87ec03257e..87185969f5 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, bpf_loader_deprecated, entrypoint::MAX_PERMITTED_DATA_INCREASE, instruction::InstructionError, keyed_account::KeyedAccount, pubkey::Pubkey, @@ -23,7 +24,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 { @@ -65,7 +66,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() { @@ -78,7 +79,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)?; @@ -177,7 +178,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() { @@ -192,14 +193,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 { @@ -228,12 +226,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)?; } @@ -410,7 +408,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!( @@ -453,7 +452,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()) { @@ -480,7 +485,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()) { @@ -509,7 +514,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 1900669cf4..28b49055ed 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, @@ -170,9 +171,11 @@ pub fn bind_syscall_context_objects<'a>( loader_id: &'a Pubkey, vm: &mut EbpfVm<'a, BpfError, crate::ThisInstructionMeter>, 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 @@ -181,6 +184,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, )?; @@ -189,6 +193,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, )?; @@ -216,6 +221,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, )?; @@ -225,6 +231,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, )?; @@ -234,6 +241,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, )?; @@ -244,6 +252,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, )?; @@ -255,6 +264,7 @@ pub fn bind_syscall_context_objects<'a>( cost: 0, compute_meter: invoke_context.get_compute_meter(), loader_id, + enforce_aligned_host_addrs, }), ); @@ -338,32 +348,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>( @@ -372,41 +403,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 @@ -416,9 +471,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, @@ -455,6 +517,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( @@ -473,6 +536,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()), ); } @@ -483,6 +547,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( @@ -502,6 +567,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) @@ -582,6 +648,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( @@ -596,7 +663,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()); @@ -655,9 +727,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()); } @@ -669,10 +747,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)) } @@ -681,6 +765,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( @@ -700,6 +785,7 @@ impl<'a> SyscallObject for SyscallCreateProgramAddress<'a> { program_id_addr, memory_mapping, self.loader_id, + self.enforce_aligned_host_addrs, ), result ); @@ -713,7 +799,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()); @@ -726,6 +818,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( @@ -745,6 +838,7 @@ impl<'a> SyscallObject for SyscallTryFindProgramAddress<'a> { program_id_addr, memory_mapping, self.loader_id, + self.enforce_aligned_host_addrs, ), result ); @@ -760,11 +854,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]; @@ -785,6 +890,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( @@ -803,14 +909,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() { @@ -819,7 +932,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 ); @@ -841,6 +955,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( @@ -856,15 +971,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; @@ -887,7 +1017,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); @@ -1030,6 +1165,7 @@ trait SyscallInvokeSigned<'a> { &self, addr: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result>; fn translate_accounts( &self, @@ -1046,6 +1182,7 @@ trait SyscallInvokeSigned<'a> { signers_seeds_addr: u64, signers_seeds_len: u64, memory_mapping: &MemoryMapping, + enforce_aligned_host_addrs: bool, ) -> Result, EbpfError>; } @@ -1069,8 +1206,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(), @@ -1083,6 +1226,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::( @@ -1090,6 +1234,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 { @@ -1109,12 +1254,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 @@ -1124,6 +1272,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>>()?; @@ -1138,13 +1287,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) = { @@ -1153,6 +1309,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()) { @@ -1174,6 +1331,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; ( @@ -1182,6 +1340,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, @@ -1225,6 +1384,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 { @@ -1233,6 +1393,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()); @@ -1243,6 +1404,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( @@ -1258,6 +1420,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>>()?; @@ -1361,34 +1524,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, @@ -1414,18 +1593,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>>()?; @@ -1437,11 +1624,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; @@ -1457,6 +1646,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; @@ -1476,6 +1666,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(( @@ -1514,6 +1705,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::( @@ -1521,6 +1713,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()); @@ -1533,6 +1726,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( @@ -1548,6 +1742,7 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { seed.addr, seed.len, self.loader_id, + enforce_aligned_host_addrs, ) }) .collect::, EbpfError>>()?; @@ -1751,18 +1946,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 = invoke_context .get_keyed_accounts() @@ -1905,7 +2108,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, @@ -1987,7 +2192,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 @@ -1997,7 +2202,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, @@ -2009,12 +2214,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] @@ -2035,9 +2240,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()); @@ -2055,9 +2265,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); @@ -2065,7 +2280,8 @@ mod tests { &memory_mapping, data.as_ptr() as u64, u64::MAX, - &bpf_loader::id() + &bpf_loader::id(), + true, ) .is_err()); @@ -2073,7 +2289,8 @@ mod tests { &memory_mapping, 100 - 1, data.len() as u64, - &bpf_loader::id() + &bpf_loader::id(), + true, ) .is_err()); @@ -2091,13 +2308,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]; @@ -2113,9 +2338,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); @@ -2143,6 +2373,7 @@ mod tests { 100, string.len() as u64, &bpf_loader::id(), + true, &mut |string: &str| { assert_eq!(string, "Gaggablaghblagh!"); Ok(42) @@ -2196,6 +2427,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( @@ -2221,6 +2453,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( @@ -2249,6 +2482,7 @@ mod tests { compute_meter, logger, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let memory_mapping = MemoryMapping::new::( vec![MemoryRegion { @@ -2318,6 +2552,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( @@ -2387,6 +2622,7 @@ mod tests { compute_meter, logger, loader_id: &bpf_loader::id(), + enforce_aligned_host_addrs: true, }; let memory_mapping = MemoryMapping::new::( vec![MemoryRegion { @@ -2433,9 +2669,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(); @@ -2455,9 +2696,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(); @@ -2476,9 +2722,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(); @@ -2498,9 +2749,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(); @@ -2594,6 +2850,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()