1.7.5: Occasional failure of CreatePipe or signal handing due to thread-unsafe code in cwdstuff::set

Corinna Vinschen corinna-cygwin@cygwin.com
Sat Sep 11 10:42:00 GMT 2010

On Sep 11 00:12, John Carey wrote:
> On Sep 04 02:26 Corinna Vinschen wrote:
> > The problem only starts with Vista.  I have no objections to use
> > undocumented features, if they work.  If there's any way to replace the
> > cwd handle with our own *and* keep the Win32 API happy, I'll take it.
> I think I've found a way to open the directory handle for backup intent
> on Vista and later versions.  Essentially, I emulate the new things that
> SetCurrentDirectory() is doing, but in order to get the necessary
> addresses, I have to do some very ugly hacks.
> The proof-of-concept code follows (and is also attached).  It includes
> an analysis of what is going on--to the extent that I know what is going
> on, of course.  Please let me know what you think.

First of all, I'm thoroughly impressed.  This looks like a lot of
detective work and I'm also impressed by the amount of time you
apparently put into this.

I'm hopeful we can create something for Cygwin from this.  I have just
a few discussing points for now.

> The PEB does NOT seem to point to any VistaCwd instances.  Instead,

That puzzles me a bit...

> After creating the new VistaCwd instance; call it newCwd, the
> SetCurrentDirectory () implementation modifies the PEB and Cwd
> under a lock on CwdCS, as follows:
>   Params.CurrentDirectoryHandle = newCwd.DirectoryHandle;
>   Params.CurrentDirectoryName.Buffer = newCwd.Path.Buffer;

...because, at this point it *does* point to the newCWD, even if only
indirectly.  Let's name the VistaCwd structure Cwd points to "curCwd"
for now.  Since we have the address of curCwd.Path.Buffer in
Params.CurrentDirectoryName.Buffer, we can infer the address of curCwd
from here, right?  It's start is just a constant offset from the Buffer

Given that, wouldn't it be potentially possible to override the content
of curCwd?  The problem is probably (just as in my old Cygwin code up to
1.7.5) to make sure that this is thread safe.  Probably we would still
need CwdCS.

>   cout << showbase << hex << (size_t)CwdCS
>        << "  <== critical section" << endl;
>   cout << showbase << hex << (size_t)Cwd
>        << "  <== Vista++ CWD struct pointer" << endl;

Is there any connection between these two addresses, like, say, they
are side by side?

Can't we find Cwd by scanning the .data segment of ntdll.h for the
address we inferred from the Params.CurrentDirectoryName.Buffer value?


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

More information about the Cygwin mailing list