Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Moves section overlap checks from ELF validation to MemoryRegion cons…
Browse files Browse the repository at this point in the history
…tructor
  • Loading branch information
Lichtso committed Apr 13, 2021
1 parent 4831f78 commit b132834
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 53 deletions.
20 changes: 10 additions & 10 deletions benches/memory_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fn bench_gapped_randomized_access_with_1024_entries(bencher: &mut Bencher) {
false,
)];
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
let mut prng = new_prng!();
bencher.iter(|| {
assert!(memory_mapping
Expand All @@ -84,7 +84,7 @@ fn bench_randomized_access_with_0001_entry(bencher: &mut Bencher) {
let content = vec![0; 1024 * 2];
let memory_regions = vec![MemoryRegion::new_from_slice(&content[..], 0, 0, false)];
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
let mut prng = new_prng!();
bencher.iter(|| {
assert!(memory_mapping
Expand All @@ -102,7 +102,7 @@ fn bench_randomized_mapping_access_with_0004_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, end_address) = generate_memory_regions(4, false, Some(&mut prng));
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, prng.gen::<u64>() % end_address, 1)
Expand All @@ -115,7 +115,7 @@ fn bench_randomized_mapping_access_with_0016_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, end_address) = generate_memory_regions(16, false, Some(&mut prng));
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, prng.gen::<u64>() % end_address, 1)
Expand All @@ -128,7 +128,7 @@ fn bench_randomized_mapping_access_with_0064_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, end_address) = generate_memory_regions(64, false, Some(&mut prng));
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, prng.gen::<u64>() % end_address, 1)
Expand All @@ -141,7 +141,7 @@ fn bench_randomized_mapping_access_with_0256_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, end_address) = generate_memory_regions(256, false, Some(&mut prng));
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, prng.gen::<u64>() % end_address, 1)
Expand All @@ -154,7 +154,7 @@ fn bench_randomized_mapping_access_with_1024_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, end_address) = generate_memory_regions(1024, false, Some(&mut prng));
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, prng.gen::<u64>() % end_address, 1)
Expand All @@ -167,7 +167,7 @@ fn bench_randomized_access_with_1024_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, end_address) = generate_memory_regions(1024, false, None);
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, prng.gen::<u64>() % end_address, 1)
Expand All @@ -180,7 +180,7 @@ fn bench_randomized_mapping_with_1024_entries(bencher: &mut Bencher) {
let mut prng = new_prng!();
let (memory_regions, _end_address) = generate_memory_regions(1024, false, Some(&mut prng));
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, 0, 1)
Expand All @@ -192,7 +192,7 @@ fn bench_randomized_mapping_with_1024_entries(bencher: &mut Bencher) {
fn bench_mapping_with_1024_entries(bencher: &mut Bencher) {
let (memory_regions, _end_address) = generate_memory_regions(1024, false, None);
let config = Config::default();
let memory_mapping = MemoryMapping::new(memory_regions, &config);
let memory_mapping = MemoryMapping::new::<UserError>(memory_regions, &config).unwrap();
bencher.iter(|| {
assert!(memory_mapping
.map::<UserError>(AccessType::Load, 0, 1)
Expand Down
21 changes: 3 additions & 18 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ pub enum ElfError {
/// Section no found
#[error("Section not found: {0}")]
SectionNotFound(String),
/// Section overlap
#[error("Section overlap found between {0} and {1}")]
SectionOverlap(String, String),
/// Relative jump out of bounds
#[error("Relative jump out of bounds at instruction #{0}")]
RelativeJumpOutOfBounds(usize),
Expand Down Expand Up @@ -379,7 +376,7 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf<E, I> {
}

// calculate the read-only section infos
let mut ro_section_infos = elf
let ro_section_infos = elf
.section_headers
.iter()
.filter_map(|section_header| {
Expand All @@ -397,22 +394,10 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EBpfElf<E, I> {
None
})
.collect::<Vec<_>>();
ro_section_infos.sort_by(|a, b| a.vaddr.cmp(&b.vaddr));
for i in 0..ro_section_infos.len() {
if ro_section_infos[i].vaddr > ebpf::MM_STACK_START {
for ro_section_info in ro_section_infos.iter() {
if ro_section_info.vaddr > ebpf::MM_STACK_START {
return Err(ElfError::OutOfBounds);
}
if i > 0
&& ro_section_infos[i - 1]
.vaddr
.saturating_add(ro_section_infos[i - 1].offset_range.len() as u64)
> ro_section_infos[i].vaddr
{
return Err(ElfError::SectionOverlap(
ro_section_infos[i - 1].name.clone(),
ro_section_infos[i].name.clone(),
));
}
}

Ok(Self {
Expand Down
23 changes: 16 additions & 7 deletions src/memory_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,25 @@ impl<'a> MemoryMapping<'a> {
}

/// Creates a new MemoryMapping structure from the given regions
pub fn new(mut regions: Vec<MemoryRegion>, config: &'a Config) -> Self {
pub fn new<E: UserDefinedError>(
mut regions: Vec<MemoryRegion>,
config: &'a Config,
) -> Result<Self, EbpfError<E>> {
let mut result = Self {
regions: vec![MemoryRegion::default(); regions.len()].into_boxed_slice(),
dense_keys: vec![0; regions.len()].into_boxed_slice(),
config,
};
regions.sort();
for index in 1..regions.len() {
let first = &regions[index - 1];
let second = &regions[index];
if first.vm_addr.saturating_add(first.len) > second.vm_addr {
return Err(EbpfError::VirtualAddressOverlap(second.vm_addr));
}
}
result.construct_eytzinger_order(&regions, 0, 0);
result
Ok(result)
}

/// Given a list of regions translate from virtual machine to host address
Expand Down Expand Up @@ -160,12 +170,11 @@ impl<'a> MemoryMapping<'a> {
index: usize,
new_len: u64,
) -> Result<(), EbpfError<E>> {
if index < self.regions.len() - 1
&& self.regions[index].vm_addr + new_len > self.regions[index + 1].vm_addr
let first = &self.regions[index];
let second = &self.regions[index + 1];
if index < self.regions.len() - 1 && first.vm_addr.saturating_add(new_len) > second.vm_addr
{
return Err(EbpfError::VirtualAddressOverlap(
self.regions[index + 1].vm_addr,
));
return Err(EbpfError::VirtualAddressOverlap(second.vm_addr));
}
self.regions[index].len = new_len;
Ok(())
Expand Down
49 changes: 32 additions & 17 deletions src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ pub const BPF_KTIME_GETNS_IDX: u32 = 5;
/// use solana_rbpf::syscalls::{BpfTimeGetNs, Result};
/// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping};
/// use solana_rbpf::vm::{Config, SyscallObject};
/// use solana_rbpf::user_error::UserError;
///
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::default()];
/// BpfTimeGetNs::call(&mut BpfTimeGetNs {}, 0, 0, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
/// BpfTimeGetNs::call(&mut BpfTimeGetNs {}, 0, 0, 0, 0, 0, &memory_mapping, &mut result);
/// let t = result.unwrap();
/// let d = t / 10u64.pow(9) / 60 / 60 / 24;
/// let h = (t / 10u64.pow(9) / 60 / 60) % 24;
Expand Down Expand Up @@ -96,10 +98,12 @@ pub const BPF_TRACE_PRINTK_IDX: u32 = 6;
/// use solana_rbpf::syscalls::{BpfTracePrintf, Result};
/// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping};
/// use solana_rbpf::vm::{Config, SyscallObject};
/// use solana_rbpf::user_error::UserError;
///
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::default()];
/// BpfTracePrintf::call(&mut BpfTracePrintf {}, 0, 0, 1, 15, 32, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
/// BpfTracePrintf::call(&mut BpfTracePrintf {}, 0, 0, 1, 15, 32, &memory_mapping, &mut result);
/// assert_eq!(result.unwrap() as usize, "BpfTracePrintf: 0x1, 0xf, 0x20\n".len());
/// ```
///
Expand Down Expand Up @@ -163,10 +167,12 @@ impl SyscallObject<UserError> for BpfTracePrintf {
/// use solana_rbpf::syscalls::{BpfGatherBytes, Result};
/// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping};
/// use solana_rbpf::vm::{Config, SyscallObject};
/// use solana_rbpf::user_error::UserError;
///
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::default()];
/// BpfGatherBytes::call(&mut BpfGatherBytes {}, 0x11, 0x22, 0x33, 0x44, 0x55, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
/// BpfGatherBytes::call(&mut BpfGatherBytes {}, 0x11, 0x22, 0x33, 0x44, 0x55, &memory_mapping, &mut result);
/// assert_eq!(result.unwrap(), 0x1122334455);
/// ```
pub struct BpfGatherBytes {}
Expand Down Expand Up @@ -201,15 +207,17 @@ impl SyscallObject<UserError> for BpfGatherBytes {
/// use solana_rbpf::syscalls::{BpfMemFrob, Result};
/// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping};
/// use solana_rbpf::vm::{Config, SyscallObject};
/// use solana_rbpf::user_error::UserError;
///
/// let val = vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33];
/// let val_va = 0x1000;
/// let memory_mapping = [MemoryRegion::new_from_slice(&val, val_va, 0, true)];
///
/// let mut result: Result = Ok(0);
/// BpfMemFrob::call(&mut BpfMemFrob {}, val_va, 8, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::new_from_slice(&val, val_va, 0, true)], &config).unwrap();
/// BpfMemFrob::call(&mut BpfMemFrob {}, val_va, 8, 0, 0, 0, &memory_mapping, &mut result);
/// assert_eq!(val, vec![0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x3b, 0x08, 0x19]);
/// BpfMemFrob::call(&mut BpfMemFrob {}, val_va, 8, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// BpfMemFrob::call(&mut BpfMemFrob {}, val_va, 8, 0, 0, 0, &memory_mapping, &mut result);
/// assert_eq!(val, vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33]);
/// ```
pub struct BpfMemFrob {}
Expand Down Expand Up @@ -265,10 +273,12 @@ impl SyscallObject<UserError> for BpfMemFrob {
/// use solana_rbpf::syscalls::{BpfSqrtI, Result};
/// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping};
/// use solana_rbpf::vm::{Config, SyscallObject};
/// use solana_rbpf::user_error::UserError;
///
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::default()];
/// BpfSqrtI::call(&mut BpfSqrtI {}, 9, 0, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
/// BpfSqrtI::call(&mut BpfSqrtI {}, 9, 0, 0, 0, 0, &memory_mapping, &mut result);
/// assert_eq!(result.unwrap(), 3);
/// ```
pub struct BpfSqrtI {}
Expand Down Expand Up @@ -300,13 +310,16 @@ impl SyscallObject<UserError> for BpfSqrtI {
/// let bar = "This is another sting.";
/// let va_foo = 0x1000;
/// let va_bar = 0x2000;
/// use solana_rbpf::user_error::UserError;
///
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::new_from_slice(foo.as_bytes(), va_foo, 0, false)];
/// BpfStrCmp::call(&mut BpfStrCmp {}, va_foo, va_foo, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::new_from_slice(foo.as_bytes(), va_foo, 0, false)], &config).unwrap();
/// BpfStrCmp::call(&mut BpfStrCmp {}, va_foo, va_foo, 0, 0, 0, &memory_mapping, &mut result);
/// assert!(result.unwrap() == 0);
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::new_from_slice(foo.as_bytes(), va_foo, 0, false), MemoryRegion::new_from_slice(bar.as_bytes(), va_bar, 0, false)];
/// BpfStrCmp::call(&mut BpfStrCmp {}, va_foo, va_bar, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::new_from_slice(foo.as_bytes(), va_foo, 0, false), MemoryRegion::new_from_slice(bar.as_bytes(), va_bar, 0, false)], &config).unwrap();
/// BpfStrCmp::call(&mut BpfStrCmp {}, va_foo, va_bar, 0, 0, 0, &memory_mapping, &mut result);
/// assert!(result.unwrap() != 0);
/// ```
pub struct BpfStrCmp {}
Expand Down Expand Up @@ -364,14 +377,16 @@ impl SyscallObject<UserError> for BpfStrCmp {
/// use solana_rbpf::syscalls::{BpfRand, Result};
/// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping};
/// use solana_rbpf::vm::{Config, SyscallObject};
/// use solana_rbpf::user_error::UserError;
///
/// unsafe {
/// libc::srand(time::precise_time_ns() as u32)
/// }
///
/// let mut result: Result = Ok(0);
/// let memory_mapping = [MemoryRegion::default()];
/// BpfRand::call(&mut BpfRand {}, 3, 6, 0, 0, 0, &MemoryMapping::new(memory_mapping.to_vec(), &Config::default()), &mut result);
/// let config = Config::default();
/// let memory_mapping = MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
/// BpfRand::call(&mut BpfRand {}, 3, 6, 0, 0, 0, &memory_mapping, &mut result);
/// let n = result.unwrap();
/// assert!(3 <= n && n <= 6);
/// ```
Expand Down
2 changes: 1 addition & 1 deletion src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EbpfVm<'a, E, I> {
executable,
program,
program_vm_addr,
memory_mapping: MemoryMapping::new(regions, &config),
memory_mapping: MemoryMapping::new(regions, &config)?,
tracer: Tracer::default(),
syscall_context_objects: vec![
std::ptr::null_mut();
Expand Down

0 comments on commit b132834

Please sign in to comment.