public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: add flag to indicate reparse points unknown to WinAPI
@ 2020-12-02 15:16 Corinna Vinschen
0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2020-12-02 15:16 UTC (permalink / raw)
To: cygwin-cvs
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=aec6479820fee5f71d50930bf0dde2bbf386bd4b
commit aec6479820fee5f71d50930bf0dde2bbf386bd4b
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Wed Dec 2 16:12:58 2020 +0100
Cygwin: add flag to indicate reparse points unknown to WinAPI
https://cygwin.com/pipermail/cygwin/2020-December/246938.html
reports a problem where, when adding a Cygwin default symlink
to $PATH since Cygwin 3.1.5, $PATH handling appears to be broken.
3.1.5 switched to WSL symlinks as Cygwin default symlinks.
A piece of code in path handling skips resolving reparse points
if they are the last component in the path. Thus a reparse point
in $PATH is not resolved but converted to Windows path syntax
verbatim.
If you do this with a WSL symlink, certain WinAPI functions fail.
The underlying $PATH handling fails to recognize the reparse
point in $PATH and returns with STATUS_IO_REPARSE_TAG_NOT_HANDLED.
As a result, the calling WinAPI function fails, most prominently
so CreateProcess.
Fix this problem by adding a PATH_REP_NOAPI bit to path_types
and a matching method path_conv::is_winapi_reparse_point().
Right now this flag is set for WSL symlinks and Cygwin AF_UNIX
sockets (new type implemented as reparse points).
The aforementioned code skipping repare point path resolution calls
is_winapi_reparse_point() rather than is_known_reparse_point(),
so now path resolution is only skipped for reparse points known
to WinAPI.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diff:
---
winsup/cygwin/path.cc | 8 ++++----
winsup/cygwin/path.h | 12 ++++++++++++
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 7e6243d32..abd3687df 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1017,7 +1017,7 @@ path_conv::check (const char *src, unsigned opt,
{
if (component == 0
&& (!(opt & PC_SYM_FOLLOW)
- || (is_known_reparse_point ()
+ || (is_winapi_reparse_point ()
&& (opt & PC_SYM_NOFOLLOW_REP))))
{
/* Usually a trailing slash requires to follow a symlink,
@@ -2622,7 +2622,7 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp,
}
RtlInitCountedUnicodeString (psymbuf, utf16_buf,
utf16_bufsize * sizeof (WCHAR));
- return PATH_SYMLINK | PATH_REP;
+ return PATH_SYMLINK | PATH_REP | PATH_REP_NOAPI;
}
return -EIO;
}
@@ -2632,10 +2632,10 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp,
if (memcmp (CYGWIN_SOCKET_GUID, &rgp->ReparseGuid, sizeof (GUID)) == 0)
#ifdef __WITH_AF_UNIX
- return PATH_SOCKET | PATH_REP;
+ return PATH_SOCKET | PATH_REP | PATH_REP_NOAPI;
#else
/* Recognize this as a reparse point but not as a socket. */
- return PATH_REP;
+ return PATH_REP | PATH_REP_NOAPI;
#endif
}
return 0;
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 45a047ad3..62bd5ddd5 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -71,6 +71,7 @@ enum path_types
PATH_SYMLINK = _BIT ( 4), /* symlink understood by Cygwin */
PATH_SOCKET = _BIT ( 5), /* AF_UNIX socket file */
PATH_RESOLVE_PROCFD = _BIT ( 6), /* fd symlink via /proc */
+ PATH_REP_NOAPI = _BIT ( 7), /* rep. point unknown to WinAPI */
PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */
};
@@ -179,7 +180,18 @@ class path_conv
}
int issymlink () const {return path_flags & PATH_SYMLINK;}
int is_lnk_symlink () const {return path_flags & PATH_LNK;}
+ /* This indicates any known reparse point */
int is_known_reparse_point () const {return path_flags & PATH_REP;}
+ /* This indicates any known reparse point, handled sanely by WinAPI.
+ The difference is crucial: WSL symlinks, for instance, are known
+ reparse points, so we want to open them as reparse points usually.
+ However they are foreign to WinAPI and not handled sanely. If one
+ is part of $PATH, WinAPI functions may fail under the hood with
+ STATUS_IO_REPARSE_TAG_NOT_HANDLED. */
+ int is_winapi_reparse_point () const
+ {
+ return (path_flags & (PATH_REP | PATH_REP_NOAPI)) == PATH_REP;
+ }
int isdevice () const {return dev.not_device (FH_FS) && dev.not_device (FH_FIFO);}
int isfifo () const {return dev.is_device (FH_FIFO);}
int isspecial () const {return dev.not_device (FH_FS);}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-12-02 15:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-02 15:16 [newlib-cygwin] Cygwin: add flag to indicate reparse points unknown to WinAPI Corinna Vinschen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).