Skip to content

Commit

Permalink
Use NonNull in check_raw_pointer's return type.
Browse files Browse the repository at this point in the history
This allows it to pack the return value into a single pointer-sized
value.
  • Loading branch information
sunfishcode committed Jul 26, 2022
1 parent fabb6d4 commit e019fbb
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 17 deletions.
27 changes: 17 additions & 10 deletions src/backend/linux_raw/vdso.rs
Expand Up @@ -82,7 +82,7 @@ fn init_from_sysinfo_ehdr() -> Option<Vdso> {
};

let hdr = &*hdr;
let pt = check_raw_pointer::<Elf_Phdr>(vdso.base_plus(hdr.e_phoff)?)?;
let pt = check_raw_pointer::<Elf_Phdr>(vdso.base_plus(hdr.e_phoff)? as *mut _)?.as_ptr();
let mut dyn_: *const Elf_Dyn = null();
let mut num_dyn = 0;

Expand Down Expand Up @@ -113,7 +113,8 @@ fn init_from_sysinfo_ehdr() -> Option<Vdso> {
return None;
}

dyn_ = check_raw_pointer::<Elf_Dyn>(vdso.base_plus(phdr.p_offset)?)?;
dyn_ = check_raw_pointer::<Elf_Dyn>(vdso.base_plus(phdr.p_offset)? as *mut _)?
.as_ptr();
num_dyn = phdr.p_memsz / size_of::<Elf_Dyn>();
} else if phdr.p_type == PT_INTERP || phdr.p_type == PT_GNU_RELRO {
// Don't trust any ELF image that has an "interpreter" or that uses
Expand Down Expand Up @@ -141,19 +142,26 @@ fn init_from_sysinfo_ehdr() -> Option<Vdso> {
let d = &*dyn_.add(i);
match d.d_tag {
DT_STRTAB => {
vdso.symstrings = check_raw_pointer::<u8>(vdso.addr_from_elf(d.d_val)?)?;
vdso.symstrings =
check_raw_pointer::<u8>(vdso.addr_from_elf(d.d_val)? as *mut _)?.as_ptr();
}
DT_SYMTAB => {
vdso.symtab = check_raw_pointer::<Elf_Sym>(vdso.addr_from_elf(d.d_val)?)?;
vdso.symtab =
check_raw_pointer::<Elf_Sym>(vdso.addr_from_elf(d.d_val)? as *mut _)?
.as_ptr();
}
DT_HASH => {
hash = check_raw_pointer::<u32>(vdso.addr_from_elf(d.d_val)?)?;
hash =
check_raw_pointer::<u32>(vdso.addr_from_elf(d.d_val)? as *mut _)?.as_ptr();
}
DT_VERSYM => {
vdso.versym = check_raw_pointer::<u16>(vdso.addr_from_elf(d.d_val)?)?;
vdso.versym =
check_raw_pointer::<u16>(vdso.addr_from_elf(d.d_val)? as *mut _)?.as_ptr();
}
DT_VERDEF => {
vdso.verdef = check_raw_pointer::<Elf_Verdef>(vdso.addr_from_elf(d.d_val)?)?;
vdso.verdef =
check_raw_pointer::<Elf_Verdef>(vdso.addr_from_elf(d.d_val)? as *mut _)?
.as_ptr();
}
DT_SYMENT => {
if d.d_val != size_of::<Elf_Sym>() {
Expand All @@ -165,9 +173,8 @@ fn init_from_sysinfo_ehdr() -> Option<Vdso> {
}
i = i.checked_add(1)?;
}
if vdso.symstrings.is_null() || vdso.symtab.is_null() || hash.is_null() {
return None; // Failed
}
// The upstream code checks `symstrings`, `symtab`, and `hash` for null;
// here, `check_raw_pointer` has already done that.

if vdso.verdef.is_null() {
vdso.versym = null();
Expand Down
13 changes: 6 additions & 7 deletions src/utils.rs
Expand Up @@ -12,19 +12,18 @@ pub(crate) fn as_mut_ptr<T>(t: &mut T) -> *mut T {
t
}

/// Convert a `*const c_void` to a `*const T`, checking that it is not null,
/// Convert a `*mut c_void` to a `*mut T`, checking that it is not null,
/// misaligned, or pointing to a region of memory that wraps around the address
/// space.
#[allow(dead_code)]
pub(crate) fn check_raw_pointer<T>(value: *const core::ffi::c_void) -> Option<*const T> {
if value.is_null()
|| (value as usize)
.checked_add(core::mem::size_of::<T>())
.is_none()
pub(crate) fn check_raw_pointer<T>(value: *mut core::ffi::c_void) -> Option<core::ptr::NonNull<T>> {
if (value as usize)
.checked_add(core::mem::size_of::<T>())
.is_none()
|| (value as usize) % core::mem::align_of::<T>() != 0
{
return None;
}

Some(value.cast())
core::ptr::NonNull::new(value.cast())
}

0 comments on commit e019fbb

Please sign in to comment.