From 807eca2eeed29916fa314a8ff8e99013adb4c24c Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Wed, 13 Jul 2022 05:56:35 +0200 Subject: [PATCH] Move SBF internals to own mod --- programs/bpf_loader/src/syscalls.rs | 265 ++++++++++++++-------------- 1 file changed, 133 insertions(+), 132 deletions(-) diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 9497f5649f822c..b87ffd21189f66 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -2027,154 +2027,154 @@ struct CallerAccount<'a> { } type TranslatedAccounts<'a> = Vec<(usize, Option>)>; -/// Stable representation of a `Vec` in the SBFv2 Rust runtime. -/// Only supports the global allocator. -// Size: 0x18 (24 bytes) -#[repr(C)] -struct RustVMVec { - ptr: u64, // 0x00 (8 bytes) - raw_cap: u64, // 0x08 (8 bytes) - raw_len: u64, // 0x10 (8 bytes) - _phantom: PhantomData, -} - -impl RustVMVec { - fn len(&self) -> usize { - // An u64 to usize conversion can only fail in the case of an overflow. - // Realistically, this only happens on 32-bit architectures. - // Assuming available memory in a VM will never exceed 4 GiB, - // "saturating" to UINT32_MAX safely reaches the "slice too large" error path - // that a comparable larger value would also trigger on a 64-bit architecture. - self.raw_len.try_into().unwrap_or(usize::MAX) +mod sbf_internal { + use super::*; + + /// Stable representation of a `Vec` in the SBFv2 Rust runtime. + /// Only supports the global allocator. + // Size: 0x18 (24 bytes) + #[repr(C)] + pub(crate) struct StdVec { + pub(crate) ptr: u64, // 0x00 (8 bytes) + pub(crate) raw_cap: u64, // 0x08 (8 bytes) + pub(crate) raw_len: u64, // 0x10 (8 bytes) + _phantom: PhantomData, } - /// Returns a slice to the elements pointed to by the Vec object. - fn translate( - &self, - memory_mapping: &MemoryMapping, - invoke_context: &InvokeContext, - ) -> Result<&[T], EbpfError> { - translate_slice( - memory_mapping, - self.ptr, - self.raw_len, - invoke_context.get_check_aligned(), - invoke_context.get_check_size(), - ) + impl StdVec { + pub(crate) fn len(&self) -> usize { + // An u64 to usize conversion can only fail in the case of an overflow. + // Realistically, this only happens on 32-bit architectures. + // Assuming available memory in a VM will never exceed 4 GiB, + // "saturating" to UINT32_MAX safely reaches the "slice too large" error path + // that a comparable larger value would also trigger on a 64-bit architecture. + self.raw_len.try_into().unwrap_or(usize::MAX) + } + + /// Returns a slice to the elements pointed to by the Vec object. + pub(crate) fn translate( + &self, + memory_mapping: &MemoryMapping, + invoke_context: &InvokeContext, + ) -> Result<&[T], EbpfError> { + translate_slice( + memory_mapping, + self.ptr, + self.raw_len, + invoke_context.get_check_aligned(), + invoke_context.get_check_size(), + ) + } } -} -/// Stable representation of a `solana_program::instruction::Instruction` -/// in the SBFv2 Rust runtime. -// Size: 0x50 (80 bytes) -#[repr(C)] -struct RustVMInstruction { - accounts: RustVMVec, // 0x00 (24 bytes) - data: RustVMVec, // 0x18 (24 bytes) - program_id: Pubkey, // 0x30 (32 bytes) -} + /// Stable representation of a `solana_program::instruction::Instruction` + /// in the SBFv2 Rust runtime. + // Size: 0x50 (80 bytes) + #[repr(C)] + pub(crate) struct Instruction { + pub(crate) accounts: StdVec, // 0x00 (24 bytes) + pub(crate) data: StdVec, // 0x18 (24 bytes) + pub(crate) program_id: Pubkey, // 0x30 (32 bytes) + } -impl RustVMInstruction { - /// Returns a reference to an Instruction object at the given VM memory address. - fn from_vm_memory<'a>( - memory_mapping: &MemoryMapping<'a>, - vm_addr: u64, - invoke_context: &InvokeContext<'_>, - ) -> Result<&'a Self, EbpfError> { - translate_type(memory_mapping, vm_addr, invoke_context.get_check_aligned()) + #[repr(C)] + pub(crate) struct Ptr { + pub(crate) ptr: u64, + _phantom: PhantomData, } -} -#[repr(C)] -struct RustVMPtr { - ptr: u64, - _phantom: PhantomData, -} + impl Ptr { + pub(crate) fn new(vm_addr: u64) -> Self { + Self { + ptr: vm_addr, + _phantom: PhantomData::default(), + } + } -impl RustVMPtr { - fn translate<'a>( - &self, - memory_mapping: &MemoryMapping, - invoke_context: &InvokeContext, - ) -> Result<&'a T, EbpfError> { - translate_type(memory_mapping, self.ptr, invoke_context.get_check_aligned()) + pub(crate) fn translate<'a>( + &self, + memory_mapping: &MemoryMapping, + invoke_context: &InvokeContext, + ) -> Result<&'a T, EbpfError> { + translate_type(memory_mapping, self.ptr, invoke_context.get_check_aligned()) + } + + pub(crate) fn translate_mut<'a>( + &self, + memory_mapping: &MemoryMapping, + invoke_context: &InvokeContext, + ) -> Result<&'a mut T, EbpfError> { + translate_type_mut(memory_mapping, self.ptr, invoke_context.get_check_aligned()) + } } - fn translate_mut<'a>( - &self, - memory_mapping: &MemoryMapping, - invoke_context: &InvokeContext, - ) -> Result<&'a mut T, EbpfError> { - translate_type_mut(memory_mapping, self.ptr, invoke_context.get_check_aligned()) + #[repr(C)] + pub(crate) struct StdRcBox { + _strong: u64, + _weak: u64, + pub(crate) value: T, } -} -#[repr(C)] -struct RustVMRcBox { - strong: u64, - weak: u64, - value: T, -} + #[repr(C)] + pub(crate) struct StdRefCell { + _borrow: i64, + pub(crate) value: T, + } -#[repr(C)] -struct RustVMRefCell { - borrow: i64, - value: T, -} + #[repr(C)] + pub(crate) struct Slice { + pub(crate) ptr: u64, + pub(crate) len: u64, + _phantom: PhantomData, + } -#[repr(C)] -struct RustVMSlice { - ptr: u64, - len: u64, - _phantom: PhantomData, -} + impl Slice { + pub(crate) fn translate<'a>( + &self, + memory_mapping: &MemoryMapping, + invoke_context: &InvokeContext, + ) -> Result<&'a [T], EbpfError> { + translate_slice( + memory_mapping, + self.ptr, + self.len, + invoke_context.get_check_aligned(), + invoke_context.get_check_size(), + ) + } -impl RustVMSlice { - fn translate<'a>( - &self, - memory_mapping: &MemoryMapping, - invoke_context: &InvokeContext, - ) -> Result<&'a [T], EbpfError> { - translate_slice( - memory_mapping, - self.ptr, - self.len, - invoke_context.get_check_aligned(), - invoke_context.get_check_size(), - ) + pub(crate) fn translate_mut<'a>( + &self, + memory_mapping: &MemoryMapping, + invoke_context: &InvokeContext, + ) -> Result<&'a mut [T], EbpfError> { + translate_slice_mut( + memory_mapping, + self.ptr, + self.len, + invoke_context.get_check_aligned(), + invoke_context.get_check_size(), + ) + } } - fn translate_mut<'a>( - &self, - memory_mapping: &MemoryMapping, - invoke_context: &InvokeContext, - ) -> Result<&'a mut [T], EbpfError> { - translate_slice_mut( - memory_mapping, - self.ptr, - self.len, - invoke_context.get_check_aligned(), - invoke_context.get_check_size(), - ) + /// Stable instruction of a `solana_program::account_info::AccountInfo` + /// in the SBFv2 Rust runtime. + // Size: 0x30 (48 bytes) + #[repr(C)] + pub(crate) struct AccountInfo { + pub(crate) key: Ptr, // 0x00 (8 bytes) + pub(crate) lamports: Ptr>>>, // 0x08 (8 bytes) + pub(crate) data: Ptr>>>, // 0x10 (8 bytes) + pub(crate) owner: Ptr, // 0x18 (8 bytes) + pub(crate) rent_epoch: u64, // 0x20 (8 bytes) + pub(crate) is_signer: bool, // 0x28 (1 byte) + pub(crate) is_writable: bool, // 0x29 (1 byte) + pub(crate) executable: bool, // 0x2a (1 byte) + _padding: [u8; 5], // 0x30 (5 bytes) } } -/// Stable instruction of a `solana_program::account_info::AccountInfo` -/// in the SBFv2 Rust runtime. -// Size: 0x30 (48 bytes) -#[repr(C)] -struct RustVMAccountInfo { - key: RustVMPtr, // 0x00 (8 bytes) - lamports: RustVMPtr>>>, // 0x08 (8 bytes) - data: RustVMPtr>>>, // 0x10 (8 bytes) - owner: RustVMPtr, // 0x18 (8 bytes) - rent_epoch: u64, // 0x20 (8 bytes) - is_signer: bool, // 0x28 (1 byte) - is_writable: bool, // 0x29 (1 byte) - executable: bool, // 0x2a (1 byte) - _padding: [u8; 5], // 0x30 (5 bytes) -} - /// Implemented by language specific data structure translators trait SyscallInvokeSigned<'a, 'b> { fn get_context_mut(&self) -> Result>, EbpfError>; @@ -2241,7 +2241,8 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> { memory_mapping: &mut MemoryMapping, invoke_context: &mut InvokeContext, ) -> Result> { - let ix = RustVMInstruction::from_vm_memory(memory_mapping, addr, invoke_context)?; + let ix: &sbf_internal::Instruction = + sbf_internal::Ptr::new(addr).translate(memory_mapping, invoke_context)?; check_instruction_size(ix.accounts.len(), ix.data.len(), invoke_context)?; @@ -2266,7 +2267,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> { memory_mapping: &mut MemoryMapping, invoke_context: &mut InvokeContext, ) -> Result, EbpfError> { - let account_infos = translate_slice::( + let account_infos = translate_slice::( memory_mapping, account_infos_addr, account_infos_len, @@ -2279,7 +2280,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> { .map(|account_info| account_info.key.translate(memory_mapping, invoke_context)) .collect::, EbpfError>>()?; - let translate = |account_info: &RustVMAccountInfo, invoke_context: &InvokeContext| { + let translate = |account_info: &sbf_internal::AccountInfo, invoke_context: &InvokeContext| { // Translate the account from user space let lamports = account_info @@ -2357,7 +2358,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> { ) -> Result, EbpfError> { let mut signers = Vec::new(); if signers_seeds_len > 0 { - let signers_seeds = translate_slice::>>( + let signers_seeds = translate_slice::>>( memory_mapping, signers_seeds_addr, signers_seeds_len,