Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,25 @@ impl<'a, A: AsRef<CStr>, E: AsRef<CStr>> StackBuilder<'a, A, E> {
let at_platform = unsafe { CStr::from_ptr(at_platform) };
Some(self.push_str(at_platform))
};
let at_random = unsafe {
// AT_RANDOM is only provided by Linux >= 2.6.29. On older kernels it is
// absent, so synthesize 16 bytes for the interpreter we are about to
// hand control to (it uses them for the stack canary / pointer guard).
let at_random_bytes: [u8; 16] = unsafe {
let ptr = getauxval(AT_RANDOM) as *const u8;
assert!(!ptr.is_null());
std::slice::from_raw_parts(ptr, 16)
let mut buf = [0u8; 16];
if !ptr.is_null() {
std::ptr::copy_nonoverlapping(ptr, buf.as_mut_ptr(), 16);
} else if let Ok(mut urandom) = std::fs::File::open("/dev/urandom") {
use std::io::Read;
// On a short or failed read the remaining bytes stay zero. An
// all-zero canary is the accepted worst case here: it is no
// worse than what glibc itself does when its AT_RANDOM is
// absent, and the alternative on these kernels is a panic.
let _ = urandom.read_exact(&mut buf);
}
buf
};
let at_random_addr = self.push_bytes(at_random);
let at_random_addr = self.push_bytes(&at_random_bytes);

// Align argc at bottom
while (self.stack_reversed.len()
Expand Down