Gate aligned program heap (#11808)

This commit is contained in:
Jack May
2020-08-24 13:21:34 -07:00
committed by GitHub
parent 40ca3ae796
commit c2e5dae7ba
3 changed files with 54 additions and 12 deletions

View File

@ -6,6 +6,7 @@ use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use solana_rbpf::EbpfVm; use solana_rbpf::EbpfVm;
use solana_sdk::{ use solana_sdk::{
account::Account, account::Account,
bpf_loader,
entrypoint_native::{ComputeMeter, InvokeContext, Logger, ProcessInstruction}, entrypoint_native::{ComputeMeter, InvokeContext, Logger, ProcessInstruction},
instruction::{CompiledInstruction, InstructionError}, instruction::{CompiledInstruction, InstructionError},
message::Message, message::Message,
@ -80,7 +81,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
let mut invoke_context = MockInvokeContext::default(); let mut invoke_context = MockInvokeContext::default();
let elf = load_elf().unwrap(); let elf = load_elf().unwrap();
let (mut vm, _) = solana_bpf_loader_program::create_vm(&elf, &[], &mut invoke_context).unwrap(); let (mut vm, _) =
solana_bpf_loader_program::create_vm(&bpf_loader::id(), &elf, &[], &mut invoke_context)
.unwrap();
println!("Interpreted:"); println!("Interpreted:");
assert_eq!( assert_eq!(

View File

@ -60,6 +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,
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,
@ -68,7 +69,8 @@ pub fn create_vm<'a>(
vm.set_verifier(bpf_verifier::check)?; vm.set_verifier(bpf_verifier::check)?;
vm.set_elf(&prog)?; vm.set_elf(&prog)?;
let heap_region = syscalls::register_syscalls(&mut vm, parameter_accounts, invoke_context)?; let heap_region =
syscalls::register_syscalls(loader_id, &mut vm, parameter_accounts, invoke_context)?;
Ok((vm, heap_region)) Ok((vm, heap_region))
} }
@ -148,8 +150,12 @@ pub fn process_instruction(
{ {
let compute_meter = invoke_context.get_compute_meter(); let compute_meter = invoke_context.get_compute_meter();
let program_account = program.try_account_ref_mut()?; let program_account = program.try_account_ref_mut()?;
let (mut vm, heap_region) = let (mut vm, heap_region) = match create_vm(
match create_vm(&program_account.data, &parameter_accounts, invoke_context) { program_id,
&program_account.data,
&parameter_accounts,
invoke_context,
) {
Ok(info) => info, Ok(info) => info,
Err(e) => { Err(e) => {
log!(logger, "Failed to create BPF VM: {}", e); log!(logger, "Failed to create BPF VM: {}", e);

View File

@ -92,6 +92,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,
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,
@ -147,6 +148,7 @@ pub fn register_syscalls<'a>(
vm.register_syscall_with_context_ex( vm.register_syscall_with_context_ex(
"sol_alloc_free_", "sol_alloc_free_",
Box::new(SyscallSolAllocFree { Box::new(SyscallSolAllocFree {
aligned: *loader_id != bpf_loader_deprecated::id(),
allocator: BPFAllocator::new(heap, MM_HEAP_START), allocator: BPFAllocator::new(heap, MM_HEAP_START),
}), }),
)?; )?;
@ -347,6 +349,7 @@ impl SyscallObject<BPFError> for SyscallLogU64 {
/// information about that memory (start address and size) is passed /// information about that memory (start address and size) is passed
/// to the VM to use for enforcement. /// to the VM to use for enforcement.
pub struct SyscallSolAllocFree { pub struct SyscallSolAllocFree {
aligned: bool,
allocator: BPFAllocator, allocator: BPFAllocator,
} }
impl SyscallObject<BPFError> for SyscallSolAllocFree { impl SyscallObject<BPFError> for SyscallSolAllocFree {
@ -360,7 +363,12 @@ impl SyscallObject<BPFError> for SyscallSolAllocFree {
_ro_regions: &[MemoryRegion], _ro_regions: &[MemoryRegion],
_rw_regions: &[MemoryRegion], _rw_regions: &[MemoryRegion],
) -> Result<u64, EbpfError<BPFError>> { ) -> Result<u64, EbpfError<BPFError>> {
let layout = match Layout::from_size_align(size as usize, align_of::<u128>()) { let align = if self.aligned {
align_of::<u128>()
} else {
align_of::<u8>()
};
let layout = match Layout::from_size_align(size as usize, align) {
Ok(layout) => layout, Ok(layout) => layout,
Err(_) => return Ok(0), Err(_) => return Ok(0),
}; };
@ -1195,6 +1203,7 @@ mod tests {
let ro_regions = &[MemoryRegion::default()]; let ro_regions = &[MemoryRegion::default()];
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)]; let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
let mut syscall = SyscallSolAllocFree { let mut syscall = SyscallSolAllocFree {
aligned: true,
allocator: BPFAllocator::new(heap, MM_HEAP_START), allocator: BPFAllocator::new(heap, MM_HEAP_START),
}; };
assert_ne!( assert_ne!(
@ -1216,12 +1225,35 @@ mod tests {
0 0
); );
} }
// many small allocs // many small unaligned allocs
{ {
let heap = vec![0_u8; 100]; let heap = vec![0_u8; 100];
let ro_regions = &[MemoryRegion::default()]; let ro_regions = &[MemoryRegion::default()];
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)]; let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
let mut syscall = SyscallSolAllocFree { let mut syscall = SyscallSolAllocFree {
aligned: false,
allocator: BPFAllocator::new(heap, MM_HEAP_START),
};
for _ in 0..100 {
assert_ne!(
syscall.call(1, 0, 0, 0, 0, ro_regions, rw_regions).unwrap(),
0
);
}
assert_eq!(
syscall
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
.unwrap(),
0
);
}
// many small aligned allocs
{
let heap = vec![0_u8; 100];
let ro_regions = &[MemoryRegion::default()];
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
let mut syscall = SyscallSolAllocFree {
aligned: true,
allocator: BPFAllocator::new(heap, MM_HEAP_START), allocator: BPFAllocator::new(heap, MM_HEAP_START),
}; };
for _ in 0..12 { for _ in 0..12 {
@ -1244,6 +1276,7 @@ mod tests {
let ro_regions = &[MemoryRegion::default()]; let ro_regions = &[MemoryRegion::default()];
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)]; let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
let mut syscall = SyscallSolAllocFree { let mut syscall = SyscallSolAllocFree {
aligned: true,
allocator: BPFAllocator::new(heap, MM_HEAP_START), allocator: BPFAllocator::new(heap, MM_HEAP_START),
}; };
let address = syscall let address = syscall