From 2cd7eb7f60208b0ffd51a9e117a8846c33b4ad41 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sat, 4 Jul 2015 22:49:30 +0200 Subject: [PATCH] Fix original stack when running signal handler on alternate stack * autoload.cc (SetThreadStackGuarantee): Import. * cygtls.h (struct _cygtls): Replace thread_context with a ucontext_t called context. * exceptions.cc (exception::handle): Exit from process via signal_exit in case sig_send returns from handling a stack overflow SIGSEGV. Explain why. (dumpstack_overflow_wrapper): Thread wrapper to create a stackdump from another thread. (signal_exit): Fix argument list to reflect three-arg signal handler. In case we have to create a stackdump for a stack overflow condition, do so from a separate thread. Explain why. (sigpacket::process): Don't run signal_exit on alternate stack. (altstack_wrapper): Wrapper function to do stack correction when calling the signal handler on an alternate stack to handle a stack overflow. Make sure to have lots of comments. (_cygtls::call_signal_handler): Drop local context variable to reduce stack pressure. Use this->context instead. Change inline assembler to call altstack_wrapper. (_cygtls::signal_debugger): Accommodate aforementioned change to struct _cygtls. * tlsoffset.h: Regenerate. * tlsoffset64.h: Regenerate. Signed-off-by: Corinna Vinschen --- winsup/cygwin/ChangeLog | 25 ++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/cygtls.h | 4 +- winsup/cygwin/exceptions.cc | 142 +++++++++++++++++++++++++++++------ winsup/cygwin/tlsoffsets.h | 116 ++++++++++++++-------------- winsup/cygwin/tlsoffsets64.h | 116 ++++++++++++++-------------- winsup/cygwin/wincap.cc | 14 ++++ winsup/cygwin/wincap.h | 7 ++ 8 files changed, 291 insertions(+), 134 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index eaa62a086..909996c47 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,28 @@ +2015-07-04 Corinna Vinschen + + * autoload.cc (SetThreadStackGuarantee): Import. + * cygtls.h (struct _cygtls): Replace thread_context with a ucontext_t + called context. + * exceptions.cc (exception::handle): Exit from process via signal_exit + in case sig_send returns from handling a stack overflow SIGSEGV. + Explain why. + (dumpstack_overflow_wrapper): Thread wrapper to create a stackdump + from another thread. + (signal_exit): Fix argument list to reflect three-arg signal handler. + In case we have to create a stackdump for a stack overflow condition, + do so from a separate thread. Explain why. + (sigpacket::process): Don't run signal_exit on alternate stack. + (altstack_wrapper): Wrapper function to do stack correction when + calling the signal handler on an alternate stack to handle a stack + overflow. Make sure to have lots of comments. + (_cygtls::call_signal_handler): Drop local context variable to reduce + stack pressure. Use this->context instead. Change inline assembler + to call altstack_wrapper. + (_cygtls::signal_debugger): Accommodate aforementioned change to + struct _cygtls. + * tlsoffset.h: Regenerate. + * tlsoffset64.h: Regenerate. + 2015-07-01 Corinna Vinschen * fork.cc (frok::parent): Set stacktop value based on requested stack diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 5832e27bf..6423a67a6 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -581,6 +581,7 @@ LoadDLLfunc (GetSystemTimePreciseAsFileTime, 4, kernel32) LoadDLLfuncEx (IdnToAscii, 20, kernel32, 1) LoadDLLfuncEx (IdnToUnicode, 20, kernel32, 1) LoadDLLfunc (LocaleNameToLCID, 8, kernel32) +LoadDLLfunc (SetThreadStackGuarantee, 4, kernel32) /* ldap functions are cdecl! */ #pragma push_macro ("mangle") diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 0944811b0..3dfffbbff 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -17,6 +17,7 @@ details. */ #include #undef _NOMNTENT_FUNCS #include +#include #define CYGTLS_INITIALIZED 0xc763173f @@ -192,7 +193,8 @@ public: siginfo_t *sigwait_info; HANDLE signal_arrived; bool will_wait_for_signal; - CONTEXT thread_context; + long __align; /* Needed to align context to 16 byte. */ + ucontext_t context; DWORD thread_id; siginfo_t infodata; struct pthread *tid; diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 90a8ff25d..0ce22d9b3 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -800,6 +800,19 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, ? (void *) e->ExceptionInformation[1] : (void *) in->_GR(ip); me.incyg++; sig_send (NULL, si, &me); /* Signal myself */ + if ((NTSTATUS) e->ExceptionCode == STATUS_STACK_OVERFLOW) + { + /* If we catched a stack overflow, and if the signal handler didn't exit + or longjmp, we're back here and about to continue, supposed to run the + offending instruction again. That works on Linux, but not on Windows. + In case of a stack overflow we're not immediately returning to the + system exception handler, but to NTDLL::__stkchk. __stkchk will then + terminate the applicaton. So what we do here is to signal our current + process again, but this time with SIG_DFL action. This creates a + stackdump and then exits through our own means. */ + global_sigs[SIGSEGV].sa_handler = SIG_DFL; + sig_send (NULL, si, &me); + } me.incyg--; e->ExceptionFlags = 0; return ExceptionContinueExecution; @@ -1237,10 +1250,20 @@ set_signal_mask (sigset_t& setmask, sigset_t newmask) sig_dispatch_pending (true); } + +DWORD WINAPI +dumpstack_overflow_wrapper (PVOID arg) +{ + cygwin_exception *exc = (cygwin_exception *) arg; + + exc->dumpstack (); + return 0; +} + /* Exit due to a signal. Should only be called from the signal thread. */ extern "C" { static void -signal_exit (int sig, siginfo_t *si) +signal_exit (int sig, siginfo_t *si, void *) { debug_printf ("exiting due to signal %d", sig); exit_state = ES_SIGNAL_EXIT; @@ -1262,7 +1285,27 @@ signal_exit (int sig, siginfo_t *si) if (try_to_debug ()) break; if (si->si_code != SI_USER && si->si_cyg) - ((cygwin_exception *) si->si_cyg)->dumpstack (); + { + cygwin_exception *exc = (cygwin_exception *) si->si_cyg; + if ((NTSTATUS) exc->exception_record ()->ExceptionCode + == STATUS_STACK_OVERFLOW) + { + /* We're handling a stack overflow so we're running low + on stack (surprise!) The dumpstack method needs lots + of stack for buffers. So what we do here is to run + dumpstack in another thread with its own stack. */ + HANDLE thread = CreateThread (&sec_none_nih, 0, + dumpstack_overflow_wrapper, + exc, 0, NULL); + if (thread) + { + WaitForSingleObject (thread, INFINITE); + CloseHandle (thread); + } + } + else + ((cygwin_exception *) si->si_cyg)->dumpstack (); + } else { CONTEXT c; @@ -1470,6 +1513,8 @@ stop: exit_sig: handler = (void *) signal_exit; thissig.sa_flags |= SA_SIGINFO; + /* Don't run signal_exit on alternate stack. */ + thissig.sa_flags &= ~SA_ONSTACK; dosig: if (have_execed) @@ -1488,6 +1533,58 @@ done: } +static void +altstack_wrapper (int sig, siginfo_t *siginfo, ucontext_t *sigctx, + void (*handler) (int, siginfo_t *, void *)) +{ + siginfo_t si = *siginfo; + ULONG guard_size = 0; + DWORD old_prot = (DWORD) -1; + PTEB teb = NtCurrentTeb (); + PVOID old_limit = NULL; + + /* Check if we're just handling a stack overflow. If so... */ + if (sig == SIGSEGV && si.si_cyg + && ((cygwin_exception *) si.si_cyg)->exception_record ()->ExceptionCode + == (DWORD) STATUS_STACK_OVERFLOW) + { + /* ...restore guard pages in original stack as if MSVCRT::_resetstkovlw + has been called. + + Compute size of guard pages. If SetThreadStackGuarantee isn't + supported, or if it returns 0, use the default guard page size. */ + if (wincap.has_set_thread_stack_guarantee ()) + SetThreadStackGuarantee (&guard_size); + if (!guard_size) + guard_size = wincap.def_guard_page_size (); + else + guard_size += wincap.page_size (); + old_limit = teb->Tib.StackLimit; + /* Amazing but true: This VirtualProtect call automatically fixes the + value of teb->Tib.StackLimit on some systems.*/ + if (VirtualProtect (teb->Tib.StackLimit, guard_size, + PAGE_READWRITE | PAGE_GUARD, &old_prot) + && old_limit == teb->Tib.StackLimit) + teb->Tib.StackLimit = (caddr_t) old_limit + guard_size; + } + handler (sig, &si, sigctx); + if (old_prot != (DWORD) -1) + { + /* Typically the handler would exit or at least perform a siglongjmp + trying to overcome a SEGV condition. However, if we return from a + segv handler after a stack overflow, we're dead. While on Linux the + process returns to the offending code and thus the handler is called + ad infinitum, on Windows the NTDLL::__stkchk function will simply kill + the process. So what we do here is to remove the guard pages again so + we can return to exception::handle. exception::handle will then call + sig_send again, this time with SIG_DFL action, so at least we get a + stackdump. */ + if (VirtualProtect ((caddr_t) teb->Tib.StackLimit - guard_size, + guard_size, old_prot, &old_prot)) + teb->Tib.StackLimit = old_limit; + } +} + int _cygtls::call_signal_handler () { @@ -1516,7 +1613,6 @@ _cygtls::call_signal_handler () siginfo_t thissi = infodata; void (*thisfunc) (int, siginfo_t *, void *) = func; - ucontext_t context; ucontext_t *thiscontext = NULL; /* Only make a context for SA_SIGINFO handlers */ @@ -1596,9 +1692,8 @@ _cygtls::call_signal_handler () /* Compute new stackbase. We start from the high address, aligned to 16 byte. */ - uintptr_t new_sp = (uintptr_t) _my_tls.altstack.ss_sp - + _my_tls.altstack.ss_size; - new_sp &= ~0xf; + uintptr_t new_sp = ((uintptr_t) _my_tls.altstack.ss_sp + + _my_tls.altstack.ss_size) & ~0xf; /* In assembler: Save regs on new stack, move to alternate stack, call thisfunc, revert stack regs. */ #ifdef __x86_64__ @@ -1620,8 +1715,9 @@ _cygtls::call_signal_handler () leaq %[SI], %%rdx # &thissi to 2nd arg reg \n\ movq %[CTX], %%r8 # thiscontext to 3rd arg reg \n\ movq %[FUNC], %%r9 # thisfunc to r9 \n\ + leaq %[WRAPPER], %%r10 # wrapper address to r10 \n\ movq %%rax, %%rsp # Move alt stack into rsp \n\ - call *%%r9 # Call thisfunc \n\ + call *%%r10 # Call wrapper \n\ movq %%rsp, %%rax # Restore clobbered regs \n\ movq 0x58(%%rax), %%rsp \n\ movq 0x50(%%rax), %%rbp \n\ @@ -1635,38 +1731,42 @@ _cygtls::call_signal_handler () [SIG] "o" (thissig), [SI] "o" (thissi), [CTX] "o" (thiscontext), - [FUNC] "o" (thisfunc) + [FUNC] "o" (thisfunc), + [WRAPPER] "o" (altstack_wrapper) : "memory"); #else /* Clobbered regs: ecx, edx, ebp, esp */ __asm__ ("\n\ movl %[NEW_SP], %%eax # Load alt stack into eax \n\ - subl $28, %%eax # Make room on alt stack for \n\ + subl $32, %%eax # Make room on alt stack for \n\ # clobbered regs and args to \n\ # signal handler \n\ - movl %%ecx, 12(%%eax) # Save other clobbered regs \n\ - movl %%edx, 16(%%eax) \n\ - movl %%ebp, 20(%%eax) \n\ - movl %%esp, 24(%%eax) \n\ + movl %%ecx, 16(%%eax) # Save clobbered regs \n\ + movl %%edx, 20(%%eax) \n\ + movl %%ebp, 24(%%eax) \n\ + movl %%esp, 28(%%eax) \n\ movl %[SIG], %%ecx # thissig to 1st arg slot \n\ movl %%ecx, (%%eax) \n\ leal %[SI], %%ecx # &thissi to 2nd arg slot \n\ movl %%ecx, 4(%%eax) \n\ movl %[CTX], %%ecx # thiscontext to 3rd arg slot\n\ movl %%ecx, 8(%%eax) \n\ - movl %[FUNC], %%ecx # thisfunc to ecx \n\ + movl %[FUNC], %%ecx # thisfunc to 4th arg slot \n\ + movl %%ecx, 12(%%eax) \n\ + leal %[WRAPPER], %%ecx # thisfunc to ecx \n\ movl %%eax, %%esp # Move alt stack into esp \n\ call *%%ecx # Call thisfunc \n\ movl %%esp, %%eax # Restore clobbered regs \n\ - movl 24(%%eax), %%esp \n\ - movl 20(%%eax), %%ebp \n\ - movl 16(%%eax), %%edx \n\ - movl 12(%%eax), %%eax \n" + movl 28(%%eax), %%esp \n\ + movl 24(%%eax), %%ebp \n\ + movl 20(%%eax), %%edx \n\ + movl 16(%%eax), %%eax \n" : : [NEW_SP] "o" (new_sp), [SIG] "o" (thissig), [SI] "o" (thissi), [CTX] "o" (thiscontext), - [FUNC] "o" (thisfunc) + [FUNC] "o" (thisfunc), + [WRAPPER] "o" (altstack_wrapper) : "memory"); #endif } @@ -1708,12 +1808,12 @@ _cygtls::signal_debugger (siginfo_t& si) #else c.Eip = retaddr (); #endif - memcpy (&thread_context, &c, sizeof (CONTEXT)); + memcpy (&context.uc_mcontext, &c, sizeof (CONTEXT)); /* Enough space for 32/64 bit addresses */ char sigmsg[2 * sizeof (_CYGWIN_SIGNAL_STRING " ffffffff ffffffffffffffff")]; __small_sprintf (sigmsg, _CYGWIN_SIGNAL_STRING " %d %y %p", - si.si_signo, thread_id, &thread_context); + si.si_signo, thread_id, &context.uc_mcontext); OutputDebugString (sigmsg); } ResumeThread (th); diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index daf610f19..13d1003e3 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -31,34 +31,36 @@ //; $tls::psignal_arrived = 2856; //; $tls::will_wait_for_signal = -9840; //; $tls::pwill_wait_for_signal = 2860; -//; $tls::thread_context = -9836; -//; $tls::pthread_context = 2864; -//; $tls::thread_id = -9120; -//; $tls::pthread_id = 3580; -//; $tls::infodata = -9116; -//; $tls::pinfodata = 3584; -//; $tls::tid = -8968; -//; $tls::ptid = 3732; -//; $tls::_ctinfo = -8964; -//; $tls::p_ctinfo = 3736; -//; $tls::andreas = -8960; -//; $tls::pandreas = 3740; -//; $tls::wq = -8956; -//; $tls::pwq = 3744; -//; $tls::sig = -8928; -//; $tls::psig = 3772; -//; $tls::incyg = -8924; -//; $tls::pincyg = 3776; -//; $tls::spinning = -8920; -//; $tls::pspinning = 3780; -//; $tls::stacklock = -8916; -//; $tls::pstacklock = 3784; -//; $tls::stackptr = -8912; -//; $tls::pstackptr = 3788; -//; $tls::stack = -8908; -//; $tls::pstack = 3792; -//; $tls::initialized = -7884; -//; $tls::pinitialized = 4816; +//; $tls::__align = -9836; +//; $tls::p__align = 2864; +//; $tls::context = -9832; +//; $tls::pcontext = 2868; +//; $tls::thread_id = -9084; +//; $tls::pthread_id = 3616; +//; $tls::infodata = -9080; +//; $tls::pinfodata = 3620; +//; $tls::tid = -8932; +//; $tls::ptid = 3768; +//; $tls::_ctinfo = -8928; +//; $tls::p_ctinfo = 3772; +//; $tls::andreas = -8924; +//; $tls::pandreas = 3776; +//; $tls::wq = -8920; +//; $tls::pwq = 3780; +//; $tls::sig = -8892; +//; $tls::psig = 3808; +//; $tls::incyg = -8888; +//; $tls::pincyg = 3812; +//; $tls::spinning = -8884; +//; $tls::pspinning = 3816; +//; $tls::stacklock = -8880; +//; $tls::pstacklock = 3820; +//; $tls::stackptr = -8876; +//; $tls::pstackptr = 3824; +//; $tls::stack = -8872; +//; $tls::pstack = 3828; +//; $tls::initialized = -7848; +//; $tls::pinitialized = 4852; //; __DATA__ #define tls_locals (-12700) @@ -91,31 +93,33 @@ #define tls_psignal_arrived (2856) #define tls_will_wait_for_signal (-9840) #define tls_pwill_wait_for_signal (2860) -#define tls_thread_context (-9836) -#define tls_pthread_context (2864) -#define tls_thread_id (-9120) -#define tls_pthread_id (3580) -#define tls_infodata (-9116) -#define tls_pinfodata (3584) -#define tls_tid (-8968) -#define tls_ptid (3732) -#define tls__ctinfo (-8964) -#define tls_p_ctinfo (3736) -#define tls_andreas (-8960) -#define tls_pandreas (3740) -#define tls_wq (-8956) -#define tls_pwq (3744) -#define tls_sig (-8928) -#define tls_psig (3772) -#define tls_incyg (-8924) -#define tls_pincyg (3776) -#define tls_spinning (-8920) -#define tls_pspinning (3780) -#define tls_stacklock (-8916) -#define tls_pstacklock (3784) -#define tls_stackptr (-8912) -#define tls_pstackptr (3788) -#define tls_stack (-8908) -#define tls_pstack (3792) -#define tls_initialized (-7884) -#define tls_pinitialized (4816) +#define tls___align (-9836) +#define tls_p__align (2864) +#define tls_context (-9832) +#define tls_pcontext (2868) +#define tls_thread_id (-9084) +#define tls_pthread_id (3616) +#define tls_infodata (-9080) +#define tls_pinfodata (3620) +#define tls_tid (-8932) +#define tls_ptid (3768) +#define tls__ctinfo (-8928) +#define tls_p_ctinfo (3772) +#define tls_andreas (-8924) +#define tls_pandreas (3776) +#define tls_wq (-8920) +#define tls_pwq (3780) +#define tls_sig (-8892) +#define tls_psig (3808) +#define tls_incyg (-8888) +#define tls_pincyg (3812) +#define tls_spinning (-8884) +#define tls_pspinning (3816) +#define tls_stacklock (-8880) +#define tls_pstacklock (3820) +#define tls_stackptr (-8876) +#define tls_pstackptr (3824) +#define tls_stack (-8872) +#define tls_pstack (3828) +#define tls_initialized (-7848) +#define tls_pinitialized (4852) diff --git a/winsup/cygwin/tlsoffsets64.h b/winsup/cygwin/tlsoffsets64.h index 3f171b0ff..d137408d0 100644 --- a/winsup/cygwin/tlsoffsets64.h +++ b/winsup/cygwin/tlsoffsets64.h @@ -31,34 +31,36 @@ //; $tls::psignal_arrived = 4152; //; $tls::will_wait_for_signal = -8640; //; $tls::pwill_wait_for_signal = 4160; -//; $tls::thread_context = -8632; -//; $tls::pthread_context = 4168; -//; $tls::thread_id = -7400; -//; $tls::pthread_id = 5400; -//; $tls::infodata = -7396; -//; $tls::pinfodata = 5404; -//; $tls::tid = -7248; -//; $tls::ptid = 5552; -//; $tls::_ctinfo = -7240; -//; $tls::p_ctinfo = 5560; -//; $tls::andreas = -7232; -//; $tls::pandreas = 5568; -//; $tls::wq = -7224; -//; $tls::pwq = 5576; -//; $tls::sig = -7176; -//; $tls::psig = 5624; -//; $tls::incyg = -7172; -//; $tls::pincyg = 5628; -//; $tls::spinning = -7168; -//; $tls::pspinning = 5632; -//; $tls::stacklock = -7164; -//; $tls::pstacklock = 5636; -//; $tls::stackptr = -7160; -//; $tls::pstackptr = 5640; -//; $tls::stack = -7152; -//; $tls::pstack = 5648; -//; $tls::initialized = -5104; -//; $tls::pinitialized = 7696; +//; $tls::__align = -8632; +//; $tls::p__align = 4168; +//; $tls::context = -8624; +//; $tls::pcontext = 4176; +//; $tls::thread_id = -7328; +//; $tls::pthread_id = 5472; +//; $tls::infodata = -7324; +//; $tls::pinfodata = 5476; +//; $tls::tid = -7176; +//; $tls::ptid = 5624; +//; $tls::_ctinfo = -7168; +//; $tls::p_ctinfo = 5632; +//; $tls::andreas = -7160; +//; $tls::pandreas = 5640; +//; $tls::wq = -7152; +//; $tls::pwq = 5648; +//; $tls::sig = -7104; +//; $tls::psig = 5696; +//; $tls::incyg = -7100; +//; $tls::pincyg = 5700; +//; $tls::spinning = -7096; +//; $tls::pspinning = 5704; +//; $tls::stacklock = -7092; +//; $tls::pstacklock = 5708; +//; $tls::stackptr = -7088; +//; $tls::pstackptr = 5712; +//; $tls::stack = -7080; +//; $tls::pstack = 5720; +//; $tls::initialized = -5032; +//; $tls::pinitialized = 7768; //; __DATA__ #define tls_locals (-12800) @@ -91,31 +93,33 @@ #define tls_psignal_arrived (4152) #define tls_will_wait_for_signal (-8640) #define tls_pwill_wait_for_signal (4160) -#define tls_thread_context (-8632) -#define tls_pthread_context (4168) -#define tls_thread_id (-7400) -#define tls_pthread_id (5400) -#define tls_infodata (-7396) -#define tls_pinfodata (5404) -#define tls_tid (-7248) -#define tls_ptid (5552) -#define tls__ctinfo (-7240) -#define tls_p_ctinfo (5560) -#define tls_andreas (-7232) -#define tls_pandreas (5568) -#define tls_wq (-7224) -#define tls_pwq (5576) -#define tls_sig (-7176) -#define tls_psig (5624) -#define tls_incyg (-7172) -#define tls_pincyg (5628) -#define tls_spinning (-7168) -#define tls_pspinning (5632) -#define tls_stacklock (-7164) -#define tls_pstacklock (5636) -#define tls_stackptr (-7160) -#define tls_pstackptr (5640) -#define tls_stack (-7152) -#define tls_pstack (5648) -#define tls_initialized (-5104) -#define tls_pinitialized (7696) +#define tls___align (-8632) +#define tls_p__align (4168) +#define tls_context (-8624) +#define tls_pcontext (4176) +#define tls_thread_id (-7328) +#define tls_pthread_id (5472) +#define tls_infodata (-7324) +#define tls_pinfodata (5476) +#define tls_tid (-7176) +#define tls_ptid (5624) +#define tls__ctinfo (-7168) +#define tls_p_ctinfo (5632) +#define tls_andreas (-7160) +#define tls_pandreas (5640) +#define tls_wq (-7152) +#define tls_pwq (5648) +#define tls_sig (-7104) +#define tls_psig (5696) +#define tls_incyg (-7100) +#define tls_pincyg (5700) +#define tls_spinning (-7096) +#define tls_pspinning (5704) +#define tls_stacklock (-7092) +#define tls_pstacklock (5708) +#define tls_stackptr (-7088) +#define tls_pstackptr (5712) +#define tls_stack (-7080) +#define tls_pstack (5720) +#define tls_initialized (-5032) +#define tls_pinitialized (7768) diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 279754a9c..2c5880e96 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -21,6 +21,7 @@ details. */ puzzled that this has never been noticed before... */ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { + def_guard_pages:1, max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE, is_server:false, has_mandatory_integrity_control:false, @@ -46,9 +47,11 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = { terminate_thread_frees_stack:false, has_precise_system_time:false, has_microsoft_accounts:false, + has_set_thread_stack_guarantee:false, }; wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { + def_guard_pages:1, max_sys_priv:SE_CREATE_GLOBAL_PRIVILEGE, is_server:false, has_mandatory_integrity_control:false, @@ -74,9 +77,11 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = { terminate_thread_frees_stack:false, has_precise_system_time:false, has_microsoft_accounts:false, + has_set_thread_stack_guarantee:true, }; wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { + def_guard_pages:1, max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, is_server:false, has_mandatory_integrity_control:true, @@ -102,9 +107,11 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { terminate_thread_frees_stack:true, has_precise_system_time:false, has_microsoft_accounts:false, + has_set_thread_stack_guarantee:true, }; wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { + def_guard_pages:1, max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, is_server:false, has_mandatory_integrity_control:true, @@ -130,9 +137,11 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { terminate_thread_frees_stack:true, has_precise_system_time:false, has_microsoft_accounts:false, + has_set_thread_stack_guarantee:true, }; wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = { + def_guard_pages:2, max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, is_server:false, has_mandatory_integrity_control:true, @@ -158,9 +167,11 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = { terminate_thread_frees_stack:true, has_precise_system_time:true, has_microsoft_accounts:true, + has_set_thread_stack_guarantee:true, }; wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = { + def_guard_pages:2, max_sys_priv:SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, is_server:false, has_mandatory_integrity_control:true, @@ -186,6 +197,7 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = { terminate_thread_frees_stack:true, has_precise_system_time:true, has_microsoft_accounts:true, + has_set_thread_stack_guarantee:true, }; wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); @@ -240,6 +252,8 @@ wincapc::init () ((wincaps *)caps)->is_server = (version.wProductType != VER_NT_WORKSTATION); #ifdef __x86_64__ wow64 = 0; + /* 64 bit systems have one more guard page than their 32 bit counterpart. */ + ++((wincaps *)caps)->def_guard_pages; #else if (NT_SUCCESS (NtQueryInformationProcess (NtCurrentProcess (), ProcessWow64Information, diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index b41a2c625..160085d77 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -14,6 +14,7 @@ details. */ struct wincaps { + DWORD def_guard_pages; DWORD max_sys_priv; unsigned is_server : 1; unsigned has_mandatory_integrity_control : 1; @@ -39,6 +40,7 @@ struct wincaps unsigned terminate_thread_frees_stack : 1; unsigned has_precise_system_time : 1; unsigned has_microsoft_accounts : 1; + unsigned has_set_thread_stack_guarantee : 1; }; class wincapc @@ -64,6 +66,10 @@ public: #define IMPLEMENT(cap) cap() const { return ((wincaps *) this->caps)->cap; } + DWORD def_guard_page_size () const + { + return ((wincaps *) this->caps)->def_guard_pages * page_size (); + } DWORD IMPLEMENT (max_sys_priv) bool IMPLEMENT (is_server) bool IMPLEMENT (has_mandatory_integrity_control) @@ -89,6 +95,7 @@ public: bool IMPLEMENT (terminate_thread_frees_stack) bool IMPLEMENT (has_precise_system_time) bool IMPLEMENT (has_microsoft_accounts) + bool IMPLEMENT (has_set_thread_stack_guarantee) #undef IMPLEMENT };