Post by Ben RUBSONWe are facing an issue with Cygwin 2.10 32 bits running on Windows 64
bits.
Issue was found running EncFS FUSE FS using WinFsp.
When forking, and calling StartServiceCtrlDispatcher, program fails with
0xC0000028 / STATUS_BAD_STACK.Testing several Cygwin versions reveals
that issue
was introduced between 2017-11-14 and 2017-12-01. And Bill (WinFsp
author) found > that compiling with -fno-stack-protector works around
the issue.There you can
https://github.com/billziss-gh/winfsp/issues/161
Could it be possible something went wrong with Cygwin ?
I wanted to add a few more details to Ben’s post, which may help us
further understand and resolve this issue. Ben has done most of the
troubleshooting work on this and I was just lucky enough to capture an
illuminating message in the debugger.
The components that participate in the discussed interaction are:
- EncFS: a POSIX/Cygwin program that implements a FUSE file system. This
program may be built with or without fstack-protector.
- Cygfuse: a Cygwin DLL that provides a FUSE binary interface (i.e. the
fuse_* symbols). This library was built with cygport under Cygwin 2.9
32-bit. I am unclear on whether this means that the library was built with
fstack-protector (likely not).
- Winfsp-x86.dll: a native Windows DLL (32-bit). Built with Visual Studio.
- WOW64: the Windows on Windows environment.
- Win64: the Windows 64-bit OS.
There are no kernel mode components (other than Windows' own) involved in
the discussed interaction.
The interactions are:
- EncFS calls fuse_main_real which resides in libcygfuse.
- Cygfuse loads winfsp-x86.dll and forwards the fuse_main_real call to it.
- Winfsp-x86.dll proceeds to bootstrap the file system. If the command
line does not include the -f switch, then daemon(3) is called. This is
done by calling back into the Cygfuse Cygwin DLL.
- Cygfuse calls daemon(3). On return it reloads/reinits winfsp-x86.dll,
because Cygwin's fork does not handle native DLL’s. It then returns
control to (the possibly reloaded!) winfsp-x86.dll.
- Winfsp-x86.dll proceeds to initialize the FUSE file system. It calls
StartServiceCtrlDispatcher in an attempt to convert the process into a
service (I wanted FUSE file systems on Windows to be easily converted into
Windows services. Failure of the StartServiceCtrlDispatcher is benign and
the WinFsp-FUSE infrastructure knows how to handle it.)
Now if EncFS is compiled under Cygwin 2.9 (32-bit or 64-bit) or it is
compiled with fno-stack-protector under Cygwin 2.10 everything works just
fine. If however EncFS is compiled with the default (presumably it
includes fstack-protector) then the EncFS daemonized process dies without
any other information.
Attaching the debugger to the daemonized process reveals that while
unwinding an (likely benign) exception deep inside
StartServiceCtrlDispatcher, RtlUnwindEx (or its friends) determines that
the stack looks wrong and raises STATUS_BAD_STACK, which is rather fatal.