Gate pointer alignment enforcement (#12176)
This commit is contained in:
parent
de4a613610
commit
ae7b15f062
|
@ -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!(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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, ®ions).unwrap(), value)
|
assert_eq!(
|
||||||
|
translate!(start, length, ®ions, &bpf_loader::id()).unwrap(),
|
||||||
|
value
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
assert!(translate!(start, length, ®ions).is_err())
|
assert!(translate!(start, length, ®ions, &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, ®ions).unwrap();
|
let translated_pubkey = translate_type!(Pubkey, 100, ®ions, &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, ®ions).unwrap();
|
let translated_instruction =
|
||||||
|
translate_type!(Instruction, 96, ®ions, &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, ®ions).is_err());
|
assert!(translate_type!(Instruction, 100, ®ions, &bpf_loader::id()).is_err());
|
||||||
regions[0].len = std::mem::size_of::<Instruction>() as u64 * 2;
|
|
||||||
assert!(translate_type!(Instruction, 100, ®ions).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(), ®ions).unwrap();
|
let translated_data =
|
||||||
|
translate_slice!(u8, 100, data.len(), ®ions, &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(), ®ions).unwrap();
|
let translated_data =
|
||||||
|
translate_slice!(Pubkey, 100, data.len(), ®ions, &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, ®ions, &mut |string: &str| {
|
translate_string_and_do(
|
||||||
assert_eq!(string, "Gaggablaghblagh!");
|
100,
|
||||||
Ok(42)
|
string.len() as u64,
|
||||||
})
|
®ions,
|
||||||
|
&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()
|
||||||
|
|
Loading…
Reference in New Issue