CIFS symlinks on network share break Cygwin

Jonathan Lanier jonathan_lanier@naughtydog.com
Sat Feb 2 02:09:00 GMT 2008


OK, so, to resurrect this issue from... oh, about 1.5 years ago (see my
post on Oct 22 2006)...  :P

Sorry for not getting back with more on this earlier, but I have been
busy.  Since it was going to be difficult to track down I ended up
reverting to the older, working Cygwin.

To quickly (re)summarize the problem:

Newer versions of Cygwin appear to be incompatible with Windows network
shares on CIFS servers.  This incompatibility arises due to the fact
that the Windows OS seems to return unexpected values for file/directory
information if the file/directory is a native symlink on the CIFS
server, which confuses Cygwin.  By native, I mean that it is a true
symlink, created from a *nix client accessing the same network share;
our CIFS server, a NetApp box, supports true symlinks.  Example: The
native Windows API function GetFileAttributesEx() returns an attribute
of 0x80 instead of 0x10 when looking up the attribute for a directory
that is a native symlink (i.e. it incorrectly thinks it's a file, not a
directory), but *only* when called from a Cygwin application.  Compiling
the same app with -mno-cygwin, or MSVC, returns 0x10 correctly as
expected.  This incorrect behavior makes it impossible to cd to the
directory; Cygwin just reports an error and refuses to change the
current directory.  File symlinks have similar problems due to the fact
that the size reported is the size of the symlink, not the size of the
file, of a symlink that points to a file.  To add to my frustration, I
found that an older version of Cygwin (1.5.14-1) worked perfectly with
no problems.

Now I'll add some new information.  All versions of Cygwin up to
1.5.19-4 work perfectly with CIFS servers.  All versions of Cygwin after
1.5.20-1, including the current (1.5.25-7 AFAIK), fail to work correctly
with CIFS servers.  I used the Cygwin time machine (as suggested by
Matthew Woehlke, awesome find - never knew about that, very helpful,
thanks!) to determine this.  I got the source for the latest
cygwin1.dll, rebuilt, and started debugging...

What I found was amazing and somewhat confusing.  I know what's breaking
it, and I'd like some assistance figuring out what to do to fix it
correctly, in the interests of getting Cygwin working again for all us
CIFS users.

I'm certain the problem lies in the Windows OS; basically, as I
originally suspected, Windows is doing something evil.  If you look at
the function set_cygwin_privileges() in winsup9/cygwin/sec_helper.cc
you'll see the following:

void
set_cygwin_privileges (HANDLE token)
{
  set_privilege (token, SE_RESTORE_PRIV, true);
  set_privilege (token, SE_BACKUP_PRIV, true);
  set_privilege (token, SE_CHANGE_NOTIFY_PRIV, !allow_traverse);
}

Now, one of these lines didn't exist pre-1.5.20-1.  That is the line
that sets SE_BACKUP_PRIV to true.  This is easily verified by looking at
the source for 1.5.19-4; that version only had 2 lines:

void
set_cygwin_privileges (HANDLE token)
{
  set_privilege (token, SE_RESTORE_PRIV, true);
  set_privilege (token, SE_CHANGE_NOTIFY_PRIV, !allow_traverse);
}

What I believe is happening is this.  Windows XP normally hides advanced
non-Windows attributes from a Windows app.  Since Windows XP doesn't
"know" about Unix-style symlinks (let's ignore reparse points, etc. for
the moment), normally an SMB/CIFS client simply returns the information
about the file or directory at the end of the link traversal.  This is
the expected behavior; a directory should be treated as a directory with
a size of 0, a file should be treated as a file with it's true size,
etc.  Now, when you set the SE_BACKUP_PRIV, Windows XP wants the process
to be in "backup" mode.  So, it wants it to see information about the
actual link, not about the item linked to.  So, directories that are
symlinks are NOT reported as directories; their size is the size of the
symlink file on the server, NOT 0; files only return the size of the
symlink, NOT the true file size, etc.  This is *exactly* what I see when
I try to run Cygwin on a CIFS share running on our NetApp box.  This
"magic" behavior is probably intended for use internally by MS backup
apps, or possibly for more advanced SFU (Services for Unix)
compatibility.  I don't know *why* they are doing this, only that they
*are*, and it totally hoses Cygwin.  As far as I can tell from the MS
knowledge base, this "extra" feature enabled when setting SE_BACKUP_NAME
is completely undocumented.

If I comment out the line that sets SE_BACKUP_PRIV to true, everything
works perfectly.

My questions:
* Is this a valid fix?
* What are the repercussions of removing the SE_BACKUP_PRIV line?
* Why was it added in 1.5.20-1 in the first place; i.e. do we really
want/need all Cygwin processes having backup privilege?

I'm really surprised that more people haven't complained about this,
because Cygwin is totally broken on CIFS network shares and has been for
some time.  I'm guessing most people are running Samba rather than a
full-featured CIFS implementation so maybe they haven't encountered this
yet?

If anyone who knows more about this than I do can chime in, it would be
much appreciated.  Also, as I stated before, I'm more than happy to help
test to fix the problem (though I'm pretty sure the fix is simply to
remove that one line of code).

Thoughts?
- Jonathan Lanier

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



More information about the Cygwin mailing list