[GHC] #10435: catastrophic exception-handling disablement on Windows Server 2008 R2
GHC
ghc-devs at haskell.org
Mon Jun 29 15:05:27 UTC 2015
#10435: catastrophic exception-handling disablement on Windows Server 2008 R2
-------------------------------------+-------------------------------------
Reporter: malcolmw | Owner: simonmar
Type: bug | Status: new
Priority: normal | Milestone:
Component: Runtime System | Version: 7.10.1
Resolution: | Keywords: windows,
Operating System: Windows | exceptions
Type of failure: Runtime crash | Architecture: x86
Blocked By: | Test Case:
Related Tickets: | Blocking:
| Differential Revisions:
-------------------------------------+-------------------------------------
Comment (by Phyx-):
So this crash happens because of `SEHOP`, on the Windows client versions
(Vista+) it is '''off''' by default (Windows 8 has it on for Microsoft
processes) but on Windows server 2008 SEHOP is '''on''' by default.
`SEHOP` is a `SEH` exploit mitigation technique which among others checks
that the `SEH` registration records ends with the default handler in
`ntdll`. http://blogs.technet.com/b/srd/archive/2009/02/02/preventing-the-
exploitation-of-seh-overwrites-with-sehop.aspx and https://www.exploit-
db.com/docs/15379.pdf for how it works.
This same error can be gotten on windows 7 (or 8) by opting in to `SEHOP`
manually http://blogs.technet.com/b/srd/archive/2009/11/20/sehop-per-
process-opt-in-support-in-windows-7.aspx . This can be done globally or
per process.
`MingW-w64` and `MSVC++` don't seem to have this problem, they both
preserve the exception chain properly.
But `GHC i686` seems to be using `Mingw` which has a different `crtmain`.
But looking at it I can't figure out why it's going wrong,
http://sourceforge.net/p/mingw/mingw-org-
wsl/ci/21762bb4a1bd0c88c38eead03f59e8d994349e83/tree/src/libcrt/crt/crt1.c#l212
unless `SetUnhandledExceptionFilter` clears the exception chain. But
that's doubtful (and calling it from `Mingw-w64 g++` didn't reproduce the
error).
This is looking like it's a bug in `libcrt` *somewhere* though I am not
entirely sure, but there's nothing in GHC's `rts` that's manually
modifying the exception chain (as far as I know).
So on the short term, what can you do?
I can think of two options:
1) compile the code to x86_64
2) opt your binary out of `SEHOP` on Windows 2008 R2
Second one is the easiest.
For GHC, we should either find out what's causing the issue and report it
upwards (but Mingw hasn't been maintained since 2012 on first glance) or
switch to MingW-w64 for both x86 and x64_86 since they seem to do it right
http://sourceforge.net/p/mingw-w64/mingw-w64/ci/8a67ab4541226a80b3ec2047347890d915126de1/tree/mingw-w64-headers/crt/excpt.h#l102
A bit more detail on what's happening:
{{{
BUGCHECK_STR: APPLICATION_FAULT_APPLICATION_FAULT_SEHOP
PRIMARY_PROBLEM_CLASS: APPLICATION_FAULT_SEHOP
DEFAULT_BUCKET_ID: APPLICATION_FAULT_SEHOP
LAST_CONTROL_TRANSFER: from 74059339 to 74efb727
STACK_TEXT:
00cedd78 74059339 e06d7363 00000001 00000003
KERNELBASE!RaiseException+0x58
00ceddb8 741e106a 00ceddd4 741e2280 026021b4
msvcr120!_CxxThrowException+0x5b
00ceddf0 004015b6 741e2104 00000000 00000000 Exception_cpp!foo+0x6a
WARNING: Stack unwind information not available. Following frames may be
wrong.
00cedef0 76f9cbaf 00000000 00cee1a4 00000000 TestExceptions+0x15b6
74aba010 80000018 00000000 00000000 00000000
ntdll!LdrpResCompareResourceNames+0x1dc
74aba034 00000000 00010000 00000409 00000048 0x80000018
}}}
When `RaiseException` is called it tried to walk the exception chain.
On load, the exception chain is:
{{{
00cefb08: ntdll!_except_handler4+0 (77b274a0)
CRT scope 0, filter: ntdll!LdrpDoDebuggerBreak+2e (77b43bf0)
func: ntdll!LdrpDoDebuggerBreak+32 (77b43bf4)
00cefca8: ntdll!_except_handler4+0 (77b274a0)
CRT scope 0, func: ntdll!LdrpInitializeProcess+16d4 (77b18e85)
00cefcf8: ntdll!_except_handler4+0 (77b274a0)
CRT scope 0, filter: ntdll!_LdrpInitialize+42ace (77b2d4a4)
func: ntdll!_LdrpInitialize+42ae1 (77b2d4b7)
}}}
But when the exception happens something's off:
{{{
0:000> gh
ModLoad: 75470000 75497000 C:\WINDOWS\SysWOW64\IMM32.DLL
ModLoad: 759b0000 75ac2000 C:\WINDOWS\SysWOW64\MSCTF.dll
(2171c.203c4): C++ EH exception - code e06d7363 (first chance)
(2171c.203c4): C++ EH exception - code e06d7363 (!!! second chance !!!)
eax=00cedd10 ebx=004e6670 ecx=00000003 edx=00000000 esi=62602200
edi=00ceddc4
eip=75b04598 esp=00cedd10 ebp=00cedd68 iopl=0 nv up ei pl nz ac po
nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b
efl=00000212
KERNELBASE!RaiseException+0x48:
75b04598 8b4c2454 mov ecx,dword ptr [esp+54h]
ss:002b:00cedd64=8a43e393
0:000> !exchain
00ceddd4: *** ERROR: Symbol file could not be found. Defaulted to export
symbols for H:\Exception.cpp.dll -
Exception_cpp!foo+ae0 (62601ae0)
00cefe88: 00000000
Invalid exception stack at 02603bc4
}}}
Without SEHOP the invalid stack is ignored, with SEHOP that fault
`(NTSTATUS) 0xe06d7363` is thrown and you get the crash you reported.
For the record, the `mingw-w64` compilers return:
{{{
00eafdd4: msvcrt!_except_handler4+0 (773c7220)
CRT scope 0, func: msvcrt!doexit+110 (773b3bcc)
00eaffcc: ntdll!_except_handler4+0 (77b274a0)
CRT scope 0, filter: ntdll!__RtlUserThreadStart+54386 (77b3f076)
func: ntdll!__RtlUserThreadStart+543cd (77b3f0bd)
00eaffe4: ntdll!FinalExceptionHandlerPad50+0 (77ad0241)
}}}
Which also correctly ends in `FinalExceptionHandler`.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10435#comment:11>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list