Skip to content

Commit eaacf34

Browse files
committed
Add alignment check to ElfBinary::new
1 parent 478ec8a commit eaacf34

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

src/binary.rs

+44
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ impl<'s> fmt::Debug for ElfBinary<'s> {
3434
impl<'s> ElfBinary<'s> {
3535
/// Create a new ElfBinary.
3636
pub fn new(region: &'s [u8]) -> Result<ElfBinary<'s>, ElfLoaderErr> {
37+
// Verify that the slice is aligned properly
38+
if !crate::is_aligned_to(region.as_ptr() as usize, crate::ALIGNMENT) {
39+
return Err(ElfLoaderErr::UnalignedMemory);
40+
}
41+
3742
let file = ElfFile::new(region)?;
3843

3944
// Parse relevant parts out of the the .dynamic section
@@ -382,3 +387,42 @@ impl<'s> ElfBinary<'s> {
382387
self.file.program_iter().filter(select_load)
383388
}
384389
}
390+
391+
#[test]
392+
fn test_load_unaligned() {
393+
use core::ops::Deref;
394+
395+
#[repr(C, align(8))]
396+
struct AlignedStackBuffer([u8; 8096]);
397+
impl Deref for AlignedStackBuffer {
398+
type Target = [u8; 8096];
399+
fn deref(&self) -> &Self::Target {
400+
&self.0
401+
}
402+
}
403+
404+
impl AlignedStackBuffer {
405+
fn slice_at_index(&self, index: usize) -> &[u8] {
406+
&self.0[index..]
407+
}
408+
409+
fn buffer_from_file(&mut self, path: &str) {
410+
let data = std::fs::read(path).unwrap();
411+
let max = core::cmp::min(data.len(), self.0.len());
412+
self.0[..max].copy_from_slice(&data[..max]);
413+
}
414+
}
415+
416+
// Read the file into an aligned buffer
417+
let mut aligned = AlignedStackBuffer([0u8; 8096]);
418+
aligned.buffer_from_file("test/test.riscv64");
419+
420+
// Verify aligned version works
421+
let result = ElfBinary::new(aligned.deref());
422+
assert!(result.is_ok());
423+
424+
// Verify unaligned version fails with appropriate error
425+
let unaligned = aligned.slice_at_index(1);
426+
let result = ElfBinary::new(unaligned);
427+
assert_eq!(result.err().unwrap(), ElfLoaderErr::UnalignedMemory);
428+
}

src/lib.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ use bitflags::bitflags;
2121
use xmas_elf::dynamic::*;
2222
use xmas_elf::program::ProgramIter;
2323

24-
pub use xmas_elf::header::Machine;
24+
pub use xmas_elf::header::{Header, Machine};
2525
pub use xmas_elf::program::{Flags, ProgramHeader, ProgramHeader64};
2626
pub use xmas_elf::sections::{Rel, Rela};
2727
pub use xmas_elf::symbol_table::{Entry, Entry64};
2828
pub use xmas_elf::{P32, P64};
2929

30+
/// Required alignment for zero-copy reads provided to xmas_elf by the
31+
/// zero crate.
32+
pub(crate) const ALIGNMENT: usize = core::mem::align_of::<Header>();
33+
3034
/// An iterator over [`ProgramHeader`] whose type is `LOAD`.
3135
pub type LoadableHeaders<'a, 'b> = Filter<ProgramIter<'a, 'b>, fn(&ProgramHeader) -> bool>;
3236
pub type PAddr = u64;
@@ -47,6 +51,7 @@ pub struct RelocationEntry {
4751
pub enum ElfLoaderErr {
4852
ElfParser { source: &'static str },
4953
OutOfMemory,
54+
UnalignedMemory,
5055
SymbolTableNotFound,
5156
UnsupportedElfFormat,
5257
UnsupportedElfVersion,
@@ -69,6 +74,7 @@ impl fmt::Display for ElfLoaderErr {
6974
match self {
7075
ElfLoaderErr::ElfParser { source } => write!(f, "Error in ELF parser: {}", source),
7176
ElfLoaderErr::OutOfMemory => write!(f, "Out of memory"),
77+
ElfLoaderErr::UnalignedMemory => write!(f, "Data must be aligned to {:?}", ALIGNMENT),
7278
ElfLoaderErr::SymbolTableNotFound => write!(f, "No symbol table in the ELF file"),
7379
ElfLoaderErr::UnsupportedElfFormat => write!(f, "ELF format not supported"),
7480
ElfLoaderErr::UnsupportedElfVersion => write!(f, "ELF version not supported"),
@@ -166,6 +172,15 @@ pub trait ElfLoader {
166172
}
167173
}
168174

175+
/// Utility function to verify alignment.
176+
///
177+
/// Note: this may be stabilized in the future as:
178+
///
179+
/// [core::ptr::is_aligned_to](https://doc.rust-lang.org/core/primitive.pointer.html#method.is_aligned_to)
180+
pub(crate) fn is_aligned_to(ptr: usize, align: usize) -> bool {
181+
ptr & (align - 1) == 0
182+
}
183+
169184
#[cfg(doctest)]
170185
mod test_readme {
171186
macro_rules! external_doc_test {

0 commit comments

Comments
 (0)