Gate pointer alignment enforcement (#12176)

This commit is contained in:
Jack May 2020-09-11 11:07:03 -07:00 committed by GitHub
parent de4a613610
commit ae7b15f062
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 228 additions and 101 deletions

View File

@ -15,7 +15,7 @@ use solana_runtime::{
loader_utils::load_program, loader_utils::load_program,
}; };
use solana_sdk::{ use solana_sdk::{
account::{create_keyed_readonly_accounts, Account, KeyedAccount}, account::{create_keyed_readonly_accounts, Account},
bpf_loader, bpf_loader_deprecated, bpf_loader, bpf_loader_deprecated,
client::SyncClient, client::SyncClient,
entrypoint::SUCCESS, entrypoint::SUCCESS,
@ -92,12 +92,12 @@ fn bench_program_alu(bencher: &mut Bencher) {
.write_u64::<LittleEndian>(ARMSTRONG_LIMIT) .write_u64::<LittleEndian>(ARMSTRONG_LIMIT)
.unwrap(); .unwrap();
inner_iter.write_u64::<LittleEndian>(0).unwrap(); inner_iter.write_u64::<LittleEndian>(0).unwrap();
let loader_id = bpf_loader::id();
let mut invoke_context = MockInvokeContext::default(); let mut invoke_context = MockInvokeContext::default();
let elf = load_elf("bench_alu").unwrap(); let elf = load_elf("bench_alu").unwrap();
let (mut vm, _) = let (mut vm, _) =
solana_bpf_loader_program::create_vm(&bpf_loader::id(), &elf, &[], &mut invoke_context) solana_bpf_loader_program::create_vm(&loader_id, &elf, &[], &mut invoke_context).unwrap();
.unwrap();
println!("Interpreted:"); println!("Interpreted:");
assert_eq!( assert_eq!(

View File

@ -70,9 +70,10 @@ fn run_program(
let mut program_account = Account::default(); let mut program_account = Account::default();
file.read_to_end(&mut program_account.data).unwrap(); file.read_to_end(&mut program_account.data).unwrap();
let loader_id = bpf_loader::id();
let mut invoke_context = MockInvokeContext::default(); let mut invoke_context = MockInvokeContext::default();
let (mut vm, heap_region) = create_vm( let (mut vm, heap_region) = create_vm(
&bpf_loader::id(), &loader_id,
&program_account.data, &program_account.data,
parameter_accounts, parameter_accounts,
&mut invoke_context, &mut invoke_context,

View File

@ -60,7 +60,7 @@ pub enum BPFError {
impl UserDefinedError for BPFError {} impl UserDefinedError for BPFError {}
pub fn create_vm<'a>( pub fn create_vm<'a>(
loader_id: &Pubkey, loader_id: &'a Pubkey,
prog: &'a [u8], prog: &'a [u8],
parameter_accounts: &'a [KeyedAccount<'a>], parameter_accounts: &'a [KeyedAccount<'a>],
invoke_context: &'a mut dyn InvokeContext, invoke_context: &'a mut dyn InvokeContext,

View File

@ -85,7 +85,7 @@ use crate::allocator_bump::BPFAllocator;
const DEFAULT_HEAP_SIZE: usize = 32 * 1024; const DEFAULT_HEAP_SIZE: usize = 32 * 1024;
pub fn register_syscalls<'a>( pub fn register_syscalls<'a>(
loader_id: &Pubkey, loader_id: &'a Pubkey,
vm: &mut EbpfVm<'a, BPFError>, vm: &mut EbpfVm<'a, BPFError>,
callers_keyed_accounts: &'a [KeyedAccount<'a>], callers_keyed_accounts: &'a [KeyedAccount<'a>],
invoke_context: &'a mut dyn InvokeContext, invoke_context: &'a mut dyn InvokeContext,
@ -94,13 +94,14 @@ pub fn register_syscalls<'a>(
// Syscall functions common across languages // Syscall functions common across languages
vm.register_syscall_ex("abort", syscall_abort)?; vm.register_syscall_ex("abort", syscall_abort)?;
vm.register_syscall_ex("sol_panic_", syscall_sol_panic)?; vm.register_syscall_with_context_ex("sol_panic_", Box::new(SyscallPanic { loader_id }))?;
vm.register_syscall_with_context_ex( vm.register_syscall_with_context_ex(
"sol_log_", "sol_log_",
Box::new(SyscallLog { Box::new(SyscallLog {
cost: compute_budget.log_units, cost: compute_budget.log_units,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
logger: invoke_context.get_logger(), logger: invoke_context.get_logger(),
loader_id,
}), }),
)?; )?;
vm.register_syscall_with_context_ex( vm.register_syscall_with_context_ex(
@ -117,6 +118,7 @@ pub fn register_syscalls<'a>(
Box::new(SyscallCreateProgramAddress { Box::new(SyscallCreateProgramAddress {
cost: compute_budget.create_program_address_units, cost: compute_budget.create_program_address_units,
compute_meter: invoke_context.get_compute_meter(), compute_meter: invoke_context.get_compute_meter(),
loader_id,
}), }),
)?; )?;
@ -128,6 +130,7 @@ pub fn register_syscalls<'a>(
Box::new(SyscallProcessSolInstructionC { Box::new(SyscallProcessSolInstructionC {
callers_keyed_accounts, callers_keyed_accounts,
invoke_context: invoke_context.clone(), invoke_context: invoke_context.clone(),
loader_id,
}), }),
)?; )?;
vm.register_syscall_with_context_ex( vm.register_syscall_with_context_ex(
@ -135,6 +138,7 @@ pub fn register_syscalls<'a>(
Box::new(SyscallProcessInstructionRust { Box::new(SyscallProcessInstructionRust {
callers_keyed_accounts, callers_keyed_accounts,
invoke_context: invoke_context.clone(), invoke_context: invoke_context.clone(),
loader_id,
}), }),
)?; )?;
} }
@ -155,7 +159,7 @@ pub fn register_syscalls<'a>(
#[macro_export] #[macro_export]
macro_rules! translate { macro_rules! translate {
($vm_addr:expr, $len:expr, $regions:expr) => { ($vm_addr:expr, $len:expr, $regions:expr, $loader_id: expr) => {
translate_addr::<BPFError>( translate_addr::<BPFError>(
$vm_addr as u64, $vm_addr as u64,
$len as usize, $len as usize,
@ -168,8 +172,10 @@ macro_rules! translate {
#[macro_export] #[macro_export]
macro_rules! translate_type_mut { macro_rules! translate_type_mut {
($t:ty, $vm_addr:expr, $regions:expr) => {{ ($t:ty, $vm_addr:expr, $regions:expr, $loader_id: expr) => {{
if ($vm_addr as u64 as *mut $t).align_offset(align_of::<$t>()) != 0 { if $loader_id != &bpf_loader_deprecated::id()
&& ($vm_addr as u64 as *mut $t).align_offset(align_of::<$t>()) != 0
{
Err(SyscallError::UnalignedPointer.into()) Err(SyscallError::UnalignedPointer.into())
} else { } else {
unsafe { unsafe {
@ -189,8 +195,8 @@ macro_rules! translate_type_mut {
} }
#[macro_export] #[macro_export]
macro_rules! translate_type { macro_rules! translate_type {
($t:ty, $vm_addr:expr, $regions:expr) => { ($t:ty, $vm_addr:expr, $regions:expr, $loader_id: expr) => {
match translate_type_mut!($t, $vm_addr, $regions) { match translate_type_mut!($t, $vm_addr, $regions, $loader_id) {
Ok(value) => Ok(&*value), Ok(value) => Ok(&*value),
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -199,8 +205,10 @@ macro_rules! translate_type {
#[macro_export] #[macro_export]
macro_rules! translate_slice_mut { macro_rules! translate_slice_mut {
($t:ty, $vm_addr:expr, $len: expr, $regions:expr) => {{ ($t:ty, $vm_addr:expr, $len: expr, $regions:expr, $loader_id: expr) => {{
if ($vm_addr as u64 as *mut $t).align_offset(align_of::<$t>()) != 0 { if $loader_id != &bpf_loader_deprecated::id()
&& ($vm_addr as u64 as *mut $t).align_offset(align_of::<$t>()) != 0
{
Err(SyscallError::UnalignedPointer.into()) Err(SyscallError::UnalignedPointer.into())
} else { } else {
match translate_addr::<BPFError>( match translate_addr::<BPFError>(
@ -218,8 +226,8 @@ macro_rules! translate_slice_mut {
} }
#[macro_export] #[macro_export]
macro_rules! translate_slice { macro_rules! translate_slice {
($t:ty, $vm_addr:expr, $len: expr, $regions:expr) => { ($t:ty, $vm_addr:expr, $len: expr, $regions:expr, $loader_id: expr) => {
match translate_slice_mut!($t, $vm_addr, $len, $regions) { match translate_slice_mut!($t, $vm_addr, $len, $regions, $loader_id) {
Ok(value) => Ok(&*value), Ok(value) => Ok(&*value),
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -232,9 +240,10 @@ fn translate_string_and_do(
addr: u64, addr: u64,
len: u64, len: u64,
regions: &[MemoryRegion], regions: &[MemoryRegion],
loader_id: &Pubkey,
work: &mut dyn FnMut(&str) -> Result<u64, EbpfError<BPFError>>, work: &mut dyn FnMut(&str) -> Result<u64, EbpfError<BPFError>>,
) -> Result<u64, EbpfError<BPFError>> { ) -> Result<u64, EbpfError<BPFError>> {
let buf = translate_slice!(u8, addr, len, regions)?; let buf = translate_slice!(u8, addr, len, regions, loader_id)?;
let i = match buf.iter().position(|byte| *byte == 0) { let i = match buf.iter().position(|byte| *byte == 0) {
Some(i) => i, Some(i) => i,
None => len as usize, None => len as usize,
@ -263,27 +272,39 @@ pub fn syscall_abort(
/// Panic syscall function, called when the BPF program calls 'sol_panic_()` /// Panic syscall function, called when the BPF program calls 'sol_panic_()`
/// Causes the BPF program to be halted immediately /// Causes the BPF program to be halted immediately
pub fn syscall_sol_panic( /// Log a user's info message
file: u64, pub struct SyscallPanic<'a> {
len: u64, loader_id: &'a Pubkey,
line: u64, }
column: u64, impl<'a> SyscallObject<BPFError> for SyscallPanic<'a> {
_arg5: u64, fn call(
ro_regions: &[MemoryRegion], &mut self,
_rw_regions: &[MemoryRegion], file: u64,
) -> Result<u64, EbpfError<BPFError>> { len: u64,
translate_string_and_do(file, len, ro_regions, &mut |string: &str| { line: u64,
Err(SyscallError::Panic(string.to_string(), line, column).into()) column: u64,
}) _arg5: u64,
ro_regions: &[MemoryRegion],
_rw_regions: &[MemoryRegion],
) -> Result<u64, EbpfError<BPFError>> {
translate_string_and_do(
file,
len,
ro_regions,
&self.loader_id,
&mut |string: &str| Err(SyscallError::Panic(string.to_string(), line, column).into()),
)
}
} }
/// Log a user's info message /// Log a user's info message
pub struct SyscallLog { pub struct SyscallLog<'a> {
cost: u64, cost: u64,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
logger: Rc<RefCell<dyn Logger>>, logger: Rc<RefCell<dyn Logger>>,
loader_id: &'a Pubkey,
} }
impl SyscallObject<BPFError> for SyscallLog { impl<'a> SyscallObject<BPFError> for SyscallLog<'a> {
fn call( fn call(
&mut self, &mut self,
addr: u64, addr: u64,
@ -300,10 +321,16 @@ impl SyscallObject<BPFError> for SyscallLog {
.try_borrow_mut() .try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?; .map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
if logger.log_enabled() { if logger.log_enabled() {
translate_string_and_do(addr, len, ro_regions, &mut |string: &str| { translate_string_and_do(
logger.log(&format!("Program log: {}", string)); addr,
Ok(0) len,
})?; ro_regions,
&self.loader_id,
&mut |string: &str| {
logger.log(&format!("Program log: {}", string));
Ok(0)
},
)?;
} }
Ok(0) Ok(0)
} }
@ -384,11 +411,12 @@ impl SyscallObject<BPFError> for SyscallSolAllocFree {
} }
/// Create a program address /// Create a program address
pub struct SyscallCreateProgramAddress { struct SyscallCreateProgramAddress<'a> {
cost: u64, cost: u64,
compute_meter: Rc<RefCell<dyn ComputeMeter>>, compute_meter: Rc<RefCell<dyn ComputeMeter>>,
loader_id: &'a Pubkey,
} }
impl SyscallObject<BPFError> for SyscallCreateProgramAddress { impl<'a> SyscallObject<BPFError> for SyscallCreateProgramAddress<'a> {
fn call( fn call(
&mut self, &mut self,
seeds_addr: u64, seeds_addr: u64,
@ -400,8 +428,9 @@ impl SyscallObject<BPFError> for SyscallCreateProgramAddress {
rw_regions: &[MemoryRegion], rw_regions: &[MemoryRegion],
) -> Result<u64, EbpfError<BPFError>> { ) -> Result<u64, EbpfError<BPFError>> {
self.compute_meter.consume(self.cost)?; self.compute_meter.consume(self.cost)?;
// TODO need ref?
let untranslated_seeds = translate_slice!(&[&u8], seeds_addr, seeds_len, ro_regions)?; let untranslated_seeds =
translate_slice!(&[&u8], seeds_addr, seeds_len, ro_regions, self.loader_id)?;
let seeds = untranslated_seeds let seeds = untranslated_seeds
.iter() .iter()
.map(|untranslated_seed| { .map(|untranslated_seed| {
@ -409,11 +438,12 @@ impl SyscallObject<BPFError> for SyscallCreateProgramAddress {
u8, u8,
untranslated_seed.as_ptr(), untranslated_seed.as_ptr(),
untranslated_seed.len(), untranslated_seed.len(),
ro_regions ro_regions,
self.loader_id
) )
}) })
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?; .collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
let program_id = translate_type!(Pubkey, program_id_addr, ro_regions)?; let program_id = translate_type!(Pubkey, program_id_addr, ro_regions, self.loader_id)?;
let new_address = match Pubkey::create_program_address(&seeds, program_id) let new_address = match Pubkey::create_program_address(&seeds, program_id)
.map_err(SyscallError::BadSeeds) .map_err(SyscallError::BadSeeds)
@ -421,7 +451,7 @@ impl SyscallObject<BPFError> for SyscallCreateProgramAddress {
Ok(address) => address, Ok(address) => address,
Err(_) => return Ok(1), Err(_) => return Ok(1),
}; };
let address = translate_slice_mut!(u8, address_addr, 32, rw_regions)?; let address = translate_slice_mut!(u8, address_addr, 32, rw_regions, self.loader_id)?;
address.copy_from_slice(new_address.as_ref()); address.copy_from_slice(new_address.as_ref());
Ok(0) Ok(0)
} }
@ -468,6 +498,7 @@ trait SyscallProcessInstruction<'a> {
pub struct SyscallProcessInstructionRust<'a> { pub struct SyscallProcessInstructionRust<'a> {
callers_keyed_accounts: &'a [KeyedAccount<'a>], callers_keyed_accounts: &'a [KeyedAccount<'a>],
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>, invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
loader_id: &'a Pubkey,
} }
impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> { impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> { fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
@ -483,15 +514,23 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
addr: u64, addr: u64,
ro_regions: &[MemoryRegion], ro_regions: &[MemoryRegion],
) -> Result<Instruction, EbpfError<BPFError>> { ) -> Result<Instruction, EbpfError<BPFError>> {
let ix = translate_type!(Instruction, addr, ro_regions)?; let ix = translate_type!(Instruction, addr, ro_regions, self.loader_id)?;
let accounts = translate_slice!( let accounts = translate_slice!(
AccountMeta, AccountMeta,
ix.accounts.as_ptr(), ix.accounts.as_ptr(),
ix.accounts.len(), ix.accounts.len(),
ro_regions ro_regions,
self.loader_id
)?
.to_vec();
let data = translate_slice!(
u8,
ix.data.as_ptr(),
ix.data.len(),
ro_regions,
self.loader_id
)? )?
.to_vec(); .to_vec();
let data = translate_slice!(u8, ix.data.as_ptr(), ix.data.len(), ro_regions)?.to_vec();
Ok(Instruction { Ok(Instruction {
program_id: ix.program_id, program_id: ix.program_id,
accounts, accounts,
@ -512,7 +551,8 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
AccountInfo, AccountInfo,
account_infos_addr, account_infos_addr,
account_infos_len, account_infos_len,
ro_regions ro_regions,
self.loader_id
)? )?
} else { } else {
&[] &[]
@ -522,26 +562,56 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
let mut refs = Vec::with_capacity(message.account_keys.len()); let mut refs = Vec::with_capacity(message.account_keys.len());
'root: for account_key in message.account_keys.iter() { 'root: for account_key in message.account_keys.iter() {
for account_info in account_infos.iter() { for account_info in account_infos.iter() {
let key = translate_type!(Pubkey, account_info.key as *const _, ro_regions)?; let key = translate_type!(
Pubkey,
account_info.key as *const _,
ro_regions,
self.loader_id
)?;
if account_key == key { if account_key == key {
let lamports = { let lamports = {
// Double translate lamports out of RefCell // Double translate lamports out of RefCell
let ptr = translate_type!(u64, account_info.lamports.as_ptr(), ro_regions)?; let ptr = translate_type!(
translate_type_mut!(u64, *ptr, rw_regions)? u64,
account_info.lamports.as_ptr(),
ro_regions,
self.loader_id
)?;
translate_type_mut!(u64, *ptr, rw_regions, self.loader_id)?
}; };
let owner = let owner = translate_type_mut!(
translate_type_mut!(Pubkey, account_info.owner as *const _, ro_regions)?; Pubkey,
account_info.owner as *const _,
ro_regions,
self.loader_id
)?;
let (data, ref_to_len_in_vm, serialized_len_ptr) = { let (data, ref_to_len_in_vm, serialized_len_ptr) = {
// Double translate data out of RefCell // Double translate data out of RefCell
let data = *translate_type!(&[u8], account_info.data.as_ptr(), ro_regions)?; let data = *translate_type!(
&[u8],
account_info.data.as_ptr(),
ro_regions,
self.loader_id
)?;
let translated = let translated =
translate!(account_info.data.as_ptr(), 8, ro_regions)? as *mut u64; translate!(account_info.data.as_ptr(), 8, ro_regions, self.loader_id)?
as *mut u64;
let ref_to_len_in_vm = unsafe { &mut *translated.offset(1) }; let ref_to_len_in_vm = unsafe { &mut *translated.offset(1) };
let ref_of_len_in_input_buffer = unsafe { data.as_ptr().offset(-8) }; let ref_of_len_in_input_buffer = unsafe { data.as_ptr().offset(-8) };
let serialized_len_ptr = let serialized_len_ptr = translate_type_mut!(
translate_type_mut!(u64, ref_of_len_in_input_buffer, rw_regions)?; u64,
ref_of_len_in_input_buffer,
rw_regions,
self.loader_id
)?;
( (
translate_slice_mut!(u8, data.as_ptr(), data.len(), rw_regions)?, translate_slice_mut!(
u8,
data.as_ptr(),
data.len(),
rw_regions,
self.loader_id
)?,
ref_to_len_in_vm, ref_to_len_in_vm,
serialized_len_ptr, serialized_len_ptr,
) )
@ -579,11 +649,21 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
) -> Result<Vec<Pubkey>, EbpfError<BPFError>> { ) -> Result<Vec<Pubkey>, EbpfError<BPFError>> {
let mut signers = Vec::new(); let mut signers = Vec::new();
if signers_seeds_len > 0 { if signers_seeds_len > 0 {
let signers_seeds = let signers_seeds = translate_slice!(
translate_slice!(&[&str], signers_seeds_addr, signers_seeds_len, ro_regions)?; &[&str],
signers_seeds_addr,
signers_seeds_len,
ro_regions,
self.loader_id
)?;
for signer_seeds in signers_seeds.iter() { for signer_seeds in signers_seeds.iter() {
let untranslated_seeds = let untranslated_seeds = translate_slice!(
translate_slice!(&str, signer_seeds.as_ptr(), signer_seeds.len(), ro_regions)?; &str,
signer_seeds.as_ptr(),
signer_seeds.len(),
ro_regions,
self.loader_id
)?;
let seeds = untranslated_seeds let seeds = untranslated_seeds
.iter() .iter()
.map(|untranslated_seed| { .map(|untranslated_seed| {
@ -591,7 +671,8 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
u8, u8,
untranslated_seed.as_ptr(), untranslated_seed.as_ptr(),
untranslated_seed.len(), untranslated_seed.len(),
ro_regions ro_regions,
self.loader_id
) )
}) })
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?; .collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
@ -679,6 +760,7 @@ struct SolSignerSeedsC {
pub struct SyscallProcessSolInstructionC<'a> { pub struct SyscallProcessSolInstructionC<'a> {
callers_keyed_accounts: &'a [KeyedAccount<'a>], callers_keyed_accounts: &'a [KeyedAccount<'a>],
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>, invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
loader_id: &'a Pubkey,
} }
impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> { impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> { fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
@ -694,19 +776,28 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
addr: u64, addr: u64,
ro_regions: &[MemoryRegion], ro_regions: &[MemoryRegion],
) -> Result<Instruction, EbpfError<BPFError>> { ) -> Result<Instruction, EbpfError<BPFError>> {
let ix_c = translate_type!(SolInstruction, addr, ro_regions)?; let ix_c = translate_type!(SolInstruction, addr, ro_regions, self.loader_id)?;
let program_id = translate_type!(Pubkey, ix_c.program_id_addr, ro_regions)?; let program_id = translate_type!(Pubkey, ix_c.program_id_addr, ro_regions, self.loader_id)?;
let meta_cs = translate_slice!( let meta_cs = translate_slice!(
SolAccountMeta, SolAccountMeta,
ix_c.accounts_addr, ix_c.accounts_addr,
ix_c.accounts_len, ix_c.accounts_len,
ro_regions ro_regions,
self.loader_id
)?; )?;
let data = translate_slice!(u8, ix_c.data_addr, ix_c.data_len, ro_regions)?.to_vec(); let data = translate_slice!(
u8,
ix_c.data_addr,
ix_c.data_len,
ro_regions,
self.loader_id
)?
.to_vec();
let accounts = meta_cs let accounts = meta_cs
.iter() .iter()
.map(|meta_c| { .map(|meta_c| {
let pubkey = translate_type!(Pubkey, meta_c.pubkey_addr, ro_regions)?; let pubkey =
translate_type!(Pubkey, meta_c.pubkey_addr, ro_regions, self.loader_id)?;
Ok(AccountMeta { Ok(AccountMeta {
pubkey: *pubkey, pubkey: *pubkey,
is_signer: meta_c.is_signer, is_signer: meta_c.is_signer,
@ -734,29 +825,45 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
SolAccountInfo, SolAccountInfo,
account_infos_addr, account_infos_addr,
account_infos_len, account_infos_len,
ro_regions ro_regions,
self.loader_id
)?; )?;
let mut accounts = Vec::with_capacity(message.account_keys.len()); let mut accounts = Vec::with_capacity(message.account_keys.len());
let mut refs = Vec::with_capacity(message.account_keys.len()); let mut refs = Vec::with_capacity(message.account_keys.len());
'root: for account_key in message.account_keys.iter() { 'root: for account_key in message.account_keys.iter() {
for account_info in account_infos.iter() { for account_info in account_infos.iter() {
let key = translate_type!(Pubkey, account_info.key_addr, ro_regions)?; let key =
translate_type!(Pubkey, account_info.key_addr, ro_regions, self.loader_id)?;
if account_key == key { if account_key == key {
let lamports = let lamports = translate_type_mut!(
translate_type_mut!(u64, account_info.lamports_addr, rw_regions)?; u64,
let owner = translate_type_mut!(Pubkey, account_info.owner_addr, ro_regions)?; account_info.lamports_addr,
rw_regions,
self.loader_id
)?;
let owner = translate_type_mut!(
Pubkey,
account_info.owner_addr,
ro_regions,
self.loader_id
)?;
let data = translate_slice_mut!( let data = translate_slice_mut!(
u8, u8,
account_info.data_addr, account_info.data_addr,
account_info.data_len, account_info.data_len,
rw_regions rw_regions,
self.loader_id
)?; )?;
let ref_to_len_in_vm = let ref_to_len_in_vm =
unsafe { &mut *(&account_info.data_len as *const u64 as u64 as *mut u64) }; unsafe { &mut *(&account_info.data_len as *const u64 as u64 as *mut u64) };
let ref_of_len_in_input_buffer = let ref_of_len_in_input_buffer =
unsafe { (account_info.data_addr as *mut u8).offset(-8) }; unsafe { (account_info.data_addr as *mut u8).offset(-8) };
let serialized_len_ptr = let serialized_len_ptr = translate_type_mut!(
translate_type_mut!(u64, ref_of_len_in_input_buffer, rw_regions)?; u64,
ref_of_len_in_input_buffer,
rw_regions,
self.loader_id
)?;
accounts.push(Rc::new(RefCell::new(Account { accounts.push(Rc::new(RefCell::new(Account {
lamports: *lamports, lamports: *lamports,
@ -793,7 +900,8 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
SolSignerSeedC, SolSignerSeedC,
signers_seeds_addr, signers_seeds_addr,
signers_seeds_len, signers_seeds_len,
ro_regions ro_regions,
self.loader_id
)?; )?;
Ok(signers_seeds Ok(signers_seeds
.iter() .iter()
@ -802,11 +910,14 @@ impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
SolSignerSeedC, SolSignerSeedC,
signer_seeds.addr, signer_seeds.addr,
signer_seeds.len, signer_seeds.len,
ro_regions ro_regions,
self.loader_id
)?; )?;
let seeds_bytes = seeds let seeds_bytes = seeds
.iter() .iter()
.map(|seed| translate_slice!(u8, seed.addr, seed.len, ro_regions)) .map(|seed| {
translate_slice!(u8, seed.addr, seed.len, ro_regions, self.loader_id)
})
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?; .collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
Pubkey::create_program_address(&seeds_bytes, program_id) Pubkey::create_program_address(&seeds_bytes, program_id)
.map_err(|err| SyscallError::BadSeeds(err).into()) .map_err(|err| SyscallError::BadSeeds(err).into())
@ -1008,9 +1119,12 @@ mod tests {
]; ];
for (ok, start, length, value) in cases { for (ok, start, length, value) in cases {
if ok { if ok {
assert_eq!(translate!(start, length, &regions).unwrap(), value) assert_eq!(
translate!(start, length, &regions, &bpf_loader::id()).unwrap(),
value
)
} else { } else {
assert!(translate!(start, length, &regions).is_err()) assert!(translate!(start, length, &regions, &bpf_loader::id()).is_err())
} }
} }
} }
@ -1025,7 +1139,7 @@ mod tests {
addr_vm: 100, addr_vm: 100,
len: std::mem::size_of::<Pubkey>() as u64, len: std::mem::size_of::<Pubkey>() as u64,
}]; }];
let translated_pubkey = translate_type!(Pubkey, 100, &regions).unwrap(); let translated_pubkey = translate_type!(Pubkey, 100, &regions, &bpf_loader::id()).unwrap();
assert_eq!(pubkey, *translated_pubkey); assert_eq!(pubkey, *translated_pubkey);
// Instruction // Instruction
@ -1040,12 +1154,11 @@ mod tests {
addr_vm: 96, addr_vm: 96,
len: std::mem::size_of::<Instruction>() as u64, len: std::mem::size_of::<Instruction>() as u64,
}]; }];
let translated_instruction = translate_type!(Instruction, 96, &regions).unwrap(); let translated_instruction =
translate_type!(Instruction, 96, &regions, &bpf_loader::id()).unwrap();
assert_eq!(instruction, *translated_instruction); assert_eq!(instruction, *translated_instruction);
regions[0].len = 1; regions[0].len = 1;
assert!(translate_type!(Instruction, 100, &regions).is_err()); assert!(translate_type!(Instruction, 100, &regions, &bpf_loader::id()).is_err());
regions[0].len = std::mem::size_of::<Instruction>() as u64 * 2;
assert!(translate_type!(Instruction, 100, &regions).is_err());
} }
#[test] #[test]
@ -1058,7 +1171,8 @@ mod tests {
addr_vm: 100, addr_vm: 100,
len: data.len() as u64, len: data.len() as u64,
}]; }];
let translated_data = translate_slice!(u8, 100, data.len(), &regions).unwrap(); let translated_data =
translate_slice!(u8, 100, data.len(), &regions, &bpf_loader::id()).unwrap();
assert_eq!(data, translated_data); assert_eq!(data, translated_data);
data[0] = 10; data[0] = 10;
assert_eq!(data, translated_data); assert_eq!(data, translated_data);
@ -1071,7 +1185,8 @@ mod tests {
addr_vm: 100, addr_vm: 100,
len: (data.len() * std::mem::size_of::<Pubkey>()) as u64, len: (data.len() * std::mem::size_of::<Pubkey>()) as u64,
}]; }];
let translated_data = translate_slice!(Pubkey, 100, data.len(), &regions).unwrap(); let translated_data =
translate_slice!(Pubkey, 100, data.len(), &regions, &bpf_loader::id()).unwrap();
assert_eq!(data, translated_data); assert_eq!(data, translated_data);
data[0] = Pubkey::new_rand(); // Both should point to same place data[0] = Pubkey::new_rand(); // Both should point to same place
assert_eq!(data, translated_data); assert_eq!(data, translated_data);
@ -1088,10 +1203,16 @@ mod tests {
}]; }];
assert_eq!( assert_eq!(
42, 42,
translate_string_and_do(100, string.len() as u64, &regions, &mut |string: &str| { translate_string_and_do(
assert_eq!(string, "Gaggablaghblagh!"); 100,
Ok(42) string.len() as u64,
}) &regions,
&bpf_loader::id(),
&mut |string: &str| {
assert_eq!(string, "Gaggablaghblagh!");
Ok(42)
}
)
.unwrap() .unwrap()
); );
} }
@ -1115,16 +1236,20 @@ mod tests {
len: string.len() as u64, len: string.len() as u64,
}; };
let rw_region = MemoryRegion::default(); let rw_region = MemoryRegion::default();
syscall_sol_panic( let mut syscall_panic = SyscallPanic {
100, loader_id: &bpf_loader::id(),
string.len() as u64, };
42, syscall_panic
84, .call(
0, 100,
&[ro_region], string.len() as u64,
&[rw_region], 42,
) 84,
.unwrap(); 0,
&[ro_region],
&[rw_region],
)
.unwrap();
} }
#[test] #[test]
@ -1141,6 +1266,7 @@ mod tests {
cost: 1, cost: 1,
compute_meter, compute_meter,
logger, logger,
loader_id: &bpf_loader::id(),
}; };
let ro_regions = &[MemoryRegion { let ro_regions = &[MemoryRegion {
addr_host: addr, addr_host: addr,
@ -1156,7 +1282,7 @@ mod tests {
assert_eq!( assert_eq!(
Err(EbpfError::AccessViolation( Err(EbpfError::AccessViolation(
"programs/bpf_loader/src/syscalls.rs".to_string(), "programs/bpf_loader/src/syscalls.rs".to_string(),
238, 247,
100, 100,
32, 32,
" regions: \n0x64-0x73".to_string() " regions: \n0x64-0x73".to_string()