4

I'm working on a native fiber/coroutine implementation – fairly standard, for each fiber, a separate stack is allocated, and to switch contexts, registers are pushed onto the source context stack and popped from the target stack. It works well, but now I hit a little problem:

I need SEH to work within a fiber (it's okay if the program terminates or strange things start to happen when an exception goes unhandled until the fiber's last stack frame, it won't). Just saving/restoring FS:[0] (along with FS:[4] and FS:[8], obviously) during the context switch and initially setting FS:[0] for newly allocated fibers to 0xFFFFFFFF (so that the exception handler set after the context switch will be the root of the chain) almost works.

To be precise, it works on all non-server Windows OSes I tested – the problem is that Windows Server 2008 and 2008 R2 have the exception chain validation (SEHOP, SEH overwrite protection) feature enabled by default, which makes RaiseException check if the original handler (somewhere in ntdll.dll) is still the root of the chain, and immediately terminates the program as if no handlers were installed otherwise.

Thus, I'm facing the problem of constructing an appropriate root frame on the stack to keep the validation code happy. Are there any (hidden?) API functions I can call to do that, or do I have to figure out what is needed to keep RtlDispatchException and friends happy and construct the appropriate _EXCEPTION_REGISTRATION entry myself? I can't just reuse the Windows-supplied one from the creating thread because it would be at the wrong address (the SEH implementation also checks if the handler address is in the boundaries given by FS:[4] and FS:[8], and possibly also if the address order is consistent).

Oh, and I'd strongly prefer not to resort to the CreateFiber WinAPI family of functions.

dnadlinger
  • 5,883
  • 4
  • 21
  • 24
  • It is surprising how far you have got. You are aware that the FS trick does only work for x86? Is your work out of curiosity or are you serious to make your own fiber implementation? As far as I know the CLR designers did try to replace the stack as well when they did hit the stack limit but failed (http://blogs.msdn.com/b/cbrumme/archive/2003/10/01/51524.aspx). It may be possible that you can trick the OS to use several stacks for one physical thread but it is very likely that future security updates will add additional barriers. – Alois Kraus Feb 12 '12 at 15:29
  • Here's another victim: http://stackoverflow.com/questions/2357102/mixing-win32-seh-with-heap-allocated-stack-frames – Hans Passant Feb 12 '12 at 15:38
  • The code is obviously x86 only, yes. The D language runtime already has its own fiber implementation, and I'd like to avoid switching to `CreateFiber` and friends because currently the Windows and Posix code paths are nicely parallel – maybe I'll have no other choice though. Anyway, I'm currently trying to replicate the necessary handlers by hand, let's see if it works out… (subject to break with future updates, I know) – dnadlinger Feb 12 '12 at 16:17
  • Generating a »fake« (because unused) `EXCEPTION_REGISTRATION` structure at the top of the chain pointing to ntdll!FinalExceptionHandler seems to do the trick – will see if it works out in practice. – dnadlinger Feb 12 '12 at 19:20

1 Answers1

1

The approach I mentioned in the comments, generating a fake EXCEPTION_REGISTRATION entry pointing to ntdll!FinalExceptionHandler seems to work in practice indeed – at least, that's what we have in the D runtime now, and so far there have been no reports of problems:

https://github.com/D-Programming-Language/druntime/blob/c39de42dd11311844c0ef90953aa65f333ea55ab/src/core/thread.d#L4027

dnadlinger
  • 5,883
  • 4
  • 21
  • 24