Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not safe to use #1

Closed
jethrogb opened this issue Nov 6, 2015 · 2 comments
Closed

Not safe to use #1

jethrogb opened this issue Nov 6, 2015 · 2 comments

Comments

@jethrogb
Copy link

jethrogb commented Nov 6, 2015

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
@alexcrichton
Copy link
Member

Thanks for the report! I have a feeling that mmap is probably a better strategy anyway (where the page mappings can actually be controlled as this is probably only allocating large stacks anyway, I'll see if I can get around to implementing guard pages.

@alexcrichton
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants