After the commit f74dc93c6359, WSL cannot start by distribution name
such as debian.exe, which has '.exe' extention but actually is an app
execution alias. This is because the commit f74dc93c6359 disabled to
follow windows reparse point by adding PC_SYM_NOFOLLOW_REP flag in
spawn.cc, that path is used for sapwning a process. As a result, the
path, that is_console_app () received, had been the reparse point of
app execution alias, then it returned false for the the path due to
open-failure because CreateFileW() cannot open an app execution alias,
while it can open normal reparse point.  If is_console_app() returns
false, standard handles for console app (such as WSL) would not be
setup. This causes that the console input cannot be transfered to the
non-cygwin app.

This patch fixes the issue by locally converting the path, which is
a path to the app execution alias, once again using PC_SYM_FOLLOW
(without PC_SYM_NOFOLLOW_REP) option path_conv for using inside of
is_console_app() to resolve the reparse point here, if the path is
an app execution alias.

Fixes: f74dc93c6359 ("fix native symlink spawn passing wrong arg0")
Reviewed-by: Johannes Schindelin <[email protected]>
Signed-off-by: Takashi Yano <[email protected]>
---
 winsup/cygwin/fhandler/termios.cc       | 23 ++++++++++++++++++-----
 winsup/cygwin/local_includes/fhandler.h |  2 +-
 winsup/cygwin/spawn.cc                  |  2 +-
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/winsup/cygwin/fhandler/termios.cc 
b/winsup/cygwin/fhandler/termios.cc
index f99ae6c80..694a5c20f 100644
--- a/winsup/cygwin/fhandler/termios.cc
+++ b/winsup/cygwin/fhandler/termios.cc
@@ -702,13 +702,26 @@ fhandler_termios::fstat (struct stat *buf)
 }
 
 static bool
-is_console_app (const WCHAR *filename)
+is_console_app (path_conv &pc)
 {
-  wchar_t *e = wcsrchr (filename, L'.');
+  tmp_pathbuf tp;
+  WCHAR *native_path = tp.w_get ();
+  pc.get_wide_win32_path (native_path);
+
+  wchar_t *e = wcsrchr (native_path, L'.');
   if (e && (wcscasecmp (e, L".bat") == 0 || wcscasecmp (e, L".cmd") == 0))
     return true;
+
+  if (pc.is_app_execution_alias ())
+    {
+      UNICODE_STRING upath;
+      RtlInitUnicodeString (&upath, native_path);
+      path_conv target (&upath, PC_SYM_FOLLOW);
+      target.get_wide_win32_path (native_path);
+    }
+
   HANDLE h;
-  h = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ,
+  h = CreateFileW (native_path, GENERIC_READ, FILE_SHARE_READ,
                   NULL, OPEN_EXISTING, 0, NULL);
   if (h == INVALID_HANDLE_VALUE)
     return true;
@@ -761,7 +774,7 @@ fhandler_termios::ioctl (unsigned int cmd, void *varg)
 
 void
 fhandler_termios::spawn_worker::setup (bool iscygwin, HANDLE h_stdin,
-                                      const WCHAR *runpath, bool nopcon,
+                                      path_conv &pc, bool nopcon,
                                       bool reset_sendsig,
                                       const WCHAR *envblock)
 {
@@ -800,7 +813,7 @@ fhandler_termios::spawn_worker::setup (bool iscygwin, 
HANDLE h_stdin,
            ptys->setup_locale ();
          }
     }
-  if (!iscygwin && ptys_primary && is_console_app (runpath))
+  if (!iscygwin && ptys_primary && is_console_app (pc))
     {
       if (h_stdin == ptys_primary->get_handle_nat ())
        stdin_is_ptys = true;
diff --git a/winsup/cygwin/local_includes/fhandler.h 
b/winsup/cygwin/local_includes/fhandler.h
index 0de82163e..16f55b4f7 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -2036,7 +2036,7 @@ class fhandler_termios: public fhandler_base
     spawn_worker () :
       ptys_need_cleanup (false), cons_need_cleanup (false),
       stdin_is_ptys (false), ptys_ttyp (NULL) {}
-    void setup (bool iscygwin, HANDLE h_stdin, const WCHAR *runpath,
+    void setup (bool iscygwin, HANDLE h_stdin, path_conv &pc,
                bool nopcon, bool reset_sendsig, const WCHAR *envblock);
     bool need_cleanup () { return ptys_need_cleanup || cons_need_cleanup; }
     void cleanup ();
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 71add8755..7d993d081 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -579,7 +579,7 @@ child_info_spawn::worker (const char *prog_arg, const char 
*const *argv,
 
       bool no_pcon = mode != _P_OVERLAY && mode != _P_WAIT;
       term_spawn_worker.setup (iscygwin (), handle (fileno_stdin, false),
-                              runpath, no_pcon, reset_sendsig, envblock);
+                              real_path, no_pcon, reset_sendsig, envblock);
 
       /* Set up needed handles for stdio */
       si.dwFlags = STARTF_USESTDHANDLES;
-- 
2.51.0

Reply via email to