From 5d3bcc864c41cf4a7906b4c54d6d544728ac8a66 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Thu, 28 Aug 2025 19:30:54 +1000 Subject: [PATCH] Fix missing alignment check for ELF note header in fuchsia support The transmute required that the alignment of bytes was correct, but nothing checked this. Use `object::pod::from_bytes` which does the transmute and includes this check. --- src/print/fuchsia.rs | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/print/fuchsia.rs b/src/print/fuchsia.rs index 01821fd9..198b961b 100644 --- a/src/print/fuchsia.rs +++ b/src/print/fuchsia.rs @@ -1,7 +1,7 @@ use core::fmt::{self, Write}; -use core::mem::{size_of, transmute}; use core::slice::from_raw_parts; use libc::c_char; +use object::NativeEndian as NE; unsafe extern "C" { // dl_iterate_phdr takes a callback that will receive a dl_phdr_info pointer @@ -118,12 +118,7 @@ const NT_GNU_BUILD_ID: u32 = 3; // Elf_Nhdr represents an ELF note header in the endianness of the target. #[allow(non_camel_case_types)] -#[repr(C)] -struct Elf_Nhdr { - n_namesz: u32, - n_descsz: u32, - n_type: u32, -} +type Elf_Nhdr = object::elf::NoteHeader32; // Note represents an ELF note (header + contents). The name is left as a u8 // slice because it is not always null terminated and rust makes it easy enough @@ -176,19 +171,14 @@ fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> { Some(out) } -// This function has no real invariants the caller must uphold other than -// perhaps that 'bytes' should be aligned for performance (and on some -// architectures correctness). The values in the Elf_Nhdr fields might -// be nonsense but this function ensures no such thing. +// This function has no invariants the caller must uphold, but it will return `None` +// if 'bytes' is not correctly aligned. The values in the Elf_Nhdr fields might be +// nonsense but this function ensures no such thing. fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> { - if size_of::() > bytes.len() { - return None; - } - // This is safe as long as there is enough space and we just confirmed that - // in the if statement above so this should not be unsafe. - let out = unsafe { transmute::<*const u8, &'a Elf_Nhdr>(bytes.as_ptr()) }; - // Note that sice_of::() is always 4-byte aligned. - *bytes = &bytes[size_of::()..]; + let (out, rest) = object::pod::from_bytes::(bytes).ok()?; + // Note that size_of::() is always a multiple of 4-bytes, so the + // 4-byte alignment is maintained. + *bytes = rest; Some(out) } @@ -204,12 +194,12 @@ impl<'a> Iterator for NoteIter<'a> { // decisions based on the type. So even if we get out complete garbage // we should still be safe. let nhdr = take_nhdr(&mut self.base)?; - let name = take_bytes_align4(nhdr.n_namesz as usize, &mut self.base)?; - let desc = take_bytes_align4(nhdr.n_descsz as usize, &mut self.base)?; + let name = take_bytes_align4(nhdr.n_namesz.get(NE) as usize, &mut self.base)?; + let desc = take_bytes_align4(nhdr.n_descsz.get(NE) as usize, &mut self.base)?; Some(Note { name: name, desc: desc, - tipe: nhdr.n_type, + tipe: nhdr.n_type.get(NE), }) } }