Skip to content

Commit

Permalink
Rollup merge of #69969 - iximeow:sigstack-guard-page, r=cuviper
Browse files Browse the repository at this point in the history
unix: Set a guard page at the end of signal stacks

This mitigates possible issues when signal stacks overflow, which could
manifest as segfaults or in unlucky circumstances possible clobbering of
other memory values as stack overflows tend to enable.

I went ahead and made a PR for this because it's a pretty small change, though if I should open an issue/RFC for this and discuss there first I'll happily do so. I've also added some example programs that demonstrate the uncomfortably clobber-happy behavior we currently have, and the segfaults that could/should result instead, [here](https://github.com/iximeow/jubilant-train).
  • Loading branch information
Centril authored Mar 19, 2020
2 parents 73c3a49 + 28eeea6 commit 4c3a5a5
Showing 1 changed file with 18 additions and 5 deletions.
23 changes: 18 additions & 5 deletions src/libstd/sys/unix/stack_overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ mod imp {
use libc::{mmap, munmap};
use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
use libc::{MAP_ANON, MAP_PRIVATE, PROT_READ, PROT_WRITE, SIGSEGV};
use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};

use crate::sys::unix::os::page_size;
use crate::sys_common::thread_info;

#[cfg(any(target_os = "linux", target_os = "android"))]
Expand Down Expand Up @@ -137,12 +138,22 @@ mod imp {
}

unsafe fn get_stackp() -> *mut libc::c_void {
let stackp =
mmap(ptr::null_mut(), SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
let stackp = mmap(
ptr::null_mut(),
SIGSTKSZ + page_size(),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON,
-1,
0,
);
if stackp == MAP_FAILED {
panic!("failed to allocate an alternative stack");
}
stackp
let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
if guard_result != 0 {
panic!("failed to set up alternative stack guard page");
}
stackp.add(page_size())
}

#[cfg(any(
Expand Down Expand Up @@ -190,7 +201,9 @@ mod imp {
ss_size: SIGSTKSZ,
};
sigaltstack(&stack, ptr::null_mut());
munmap(handler._data, SIGSTKSZ);
// We know from `get_stackp` that the alternate stack we installed is part of a mapping
// that started one page earlier, so walk back a page and unmap from there.
munmap(handler._data.sub(page_size()), SIGSTKSZ + page_size());
}
}
}
Expand Down

0 comments on commit 4c3a5a5

Please sign in to comment.