Closed
Description
When moving the stack to the heap, there is no guard page at the end of the new stack. This results in a potential stack-to-heap overflow.
extern crate stacker;
extern crate libc;
struct Data<'a>(usize,&'a u32);
fn recurse(arg: &mut [u8], data: &Data) {
use std::sync::{Once, ONCE_INIT};
static START: Once = ONCE_INIT;
static GROWN: Once = ONCE_INIT;
let &Data(limit,guard)=data;
let ptr=&arg[0] as *const _;
START.call_once(||{println!("start, arg @ {:?}",ptr)});
if *guard != 0xDEADBEEF {
panic!("Heap guard overwritten! arg @ {:?}",ptr as *const u8);
}
let f=||{recurse(&mut [0u8;1024*32],data);};
if (arg as *const _ as *const u8 as usize) < limit {
GROWN.call_once(||{println!("grown, arg @ {:?}",ptr)});
f();
} else {
stacker::maybe_grow(64*1024,1024*1024,f);
}
}
pub fn main() {
use std::{mem,iter};
let guardvec: Vec<u32>=iter::repeat(0xDEADBEEF).take(1024).collect();
println!("guard @ {:?}",&guardvec[1023] as *const _);
let limit=unsafe {
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
assert_eq!(libc::pthread_getattr_np(libc::pthread_self(),
&mut attr), 0);
let mut stackaddr = 0 as *mut _;
let mut stacksize = 0;
assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
&mut stacksize), 0);
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
stackaddr
};
println!("stack limit {:?}",limit);
recurse(&mut [0u8;1024*32],&Data(limit as usize,&guardvec[1023]));
}
guard @ 0x7fbf17c2effc
stack limit 0x7ffce055f000
start, arg @ 0x7ffce0d54070
grown, arg @ 0x7fbf17d2af80
thread '' panicked at 'Heap guard overwritten! arg @ 0x7fbf17c28580', src/main.rs:17
Metadata
Metadata
Assignees
Labels
No labels