Skip to content

Commit a8b55f0

Browse files
Merge of #725: 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. Also include docs that reflect the current behavior of `take_nhdr`.
2 parents a405950 + 0b83800 commit a8b55f0

File tree

1 file changed

+13
-22
lines changed

1 file changed

+13
-22
lines changed

src/print/fuchsia.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::fmt::{self, Write};
2-
use core::mem::{size_of, transmute};
32
use core::slice::from_raw_parts;
43
use libc::c_char;
4+
use object::NativeEndian as NE;
55

66
unsafe extern "C" {
77
// 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;
118118

119119
// Elf_Nhdr represents an ELF note header in the endianness of the target.
120120
#[allow(non_camel_case_types)]
121-
#[repr(C)]
122-
struct Elf_Nhdr {
123-
n_namesz: u32,
124-
n_descsz: u32,
125-
n_type: u32,
126-
}
121+
type Elf_Nhdr = object::elf::NoteHeader32<NE>;
127122

128123
// Note represents an ELF note (header + contents). The name is left as a u8
129124
// slice because it is not always null terminated and rust makes it easy enough
@@ -176,19 +171,15 @@ fn take_bytes_align4<'a>(num: usize, bytes: &mut &'a [u8]) -> Option<&'a [u8]> {
176171
Some(out)
177172
}
178173

179-
// This function has no real invariants the caller must uphold other than
180-
// perhaps that 'bytes' should be aligned for performance (and on some
181-
// architectures correctness). The values in the Elf_Nhdr fields might
182-
// be nonsense but this function ensures no such thing.
174+
/// This function has no invariants the caller must uphold, but
175+
/// it will return `None`, without mutating, if `bytes` has insufficient size or alignment.
176+
/// If this returns `Some(nhdr)`, then `bytes` was and remains 4-byte-aligned.
177+
/// The values in the Elf_Nhdr fields might be nonsense.
183178
fn take_nhdr<'a>(bytes: &mut &'a [u8]) -> Option<&'a Elf_Nhdr> {
184-
if size_of::<Elf_Nhdr>() > bytes.len() {
185-
return None;
186-
}
187-
// This is safe as long as there is enough space and we just confirmed that
188-
// in the if statement above so this should not be unsafe.
189-
let out = unsafe { transmute::<*const u8, &'a Elf_Nhdr>(bytes.as_ptr()) };
190-
// Note that sice_of::<Elf_Nhdr>() is always 4-byte aligned.
191-
*bytes = &bytes[size_of::<Elf_Nhdr>()..];
179+
let (out, rest) = object::pod::from_bytes::<Elf_Nhdr>(bytes).ok()?;
180+
// Note that size_of::<Elf_Nhdr>() is always a multiple of 4-bytes, so the
181+
// 4-byte alignment is maintained.
182+
*bytes = rest;
192183
Some(out)
193184
}
194185

@@ -204,12 +195,12 @@ impl<'a> Iterator for NoteIter<'a> {
204195
// decisions based on the type. So even if we get out complete garbage
205196
// we should still be safe.
206197
let nhdr = take_nhdr(&mut self.base)?;
207-
let name = take_bytes_align4(nhdr.n_namesz as usize, &mut self.base)?;
208-
let desc = take_bytes_align4(nhdr.n_descsz as usize, &mut self.base)?;
198+
let name = take_bytes_align4(nhdr.n_namesz.get(NE) as usize, &mut self.base)?;
199+
let desc = take_bytes_align4(nhdr.n_descsz.get(NE) as usize, &mut self.base)?;
209200
Some(Note {
210201
name: name,
211202
desc: desc,
212-
tipe: nhdr.n_type,
203+
tipe: nhdr.n_type.get(NE),
213204
})
214205
}
215206
}

0 commit comments

Comments
 (0)