public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
From: Corinna Vinschen <corinna@sourceware.org>
To: cygwin-cvs@sourceware.org
Subject: [newlib-cygwin/main] Do not rely on `getenv ("HOME")`'s path conversion
Date: Tue,  6 Jun 2023 13:32:40 +0000 (GMT)	[thread overview]
Message-ID: <20230606133240.40C243858D33@sourceware.org> (raw)

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=80ff7bc26ca97a7e2194554c21fe25cbdf227813

commit 80ff7bc26ca97a7e2194554c21fe25cbdf227813
Author:     Johannes Schindelin <johannes.schindelin@gmx.de>
AuthorDate: Mon May 22 13:13:02 2023 +0200
Commit:     Corinna Vinschen <corinna@vinschen.de>
CommitDate: Tue Jun 6 15:18:53 2023 +0200

    Do not rely on `getenv ("HOME")`'s path conversion
    
    In the very early code path where `dll_crt0_1 ()` calls
    `user_shared->initialize ()`, the Cygwin runtime calls `internal_pwsid ()`
    to initialize the user name in preparation for reading the `fstab` file.
    
    In case `db_home: env` is defined in `/etc/nsswitch.conf`, we need to
    look at the environment variable `HOME` and use it, if set.
    
    When all of this happens, though, the `pinfo_init ()` function has had no
    chance to run yet (and therefore, `environ_init ()`). At this stage,
    therefore, `getenv ()`'s `findenv_func ()` call still finds `getearly ()`
    and we get the _verbatim_ value of `HOME`. That is, the Windows form.
    But we need the "POSIX" form.
    
    To add insult to injury, later calls to `getpwuid (getuid ())` will
    receive a cached version of the home directory via
    `cygheap->pg.pwd_cache.win.find_user ()` thanks to the first
    `internal_pwsid ()` call caching the result via
    `add_user_from_cygserver ()`, read: we will never receive the converted
    `HOME` but always the Windows variant.
    
    So, contrary to the assumptions made in 27376c60a9 (Allow deriving the
    current user's home directory via the HOME variable, 2023-03-28), we
    cannot assume that `getenv ("HOME")` returned a "POSIX" path.
    
    This is a real problem. Even setting aside that common callers of
    `getpwuid ()` (such as OpenSSH) are unable to handle Windows paths in the
    `pw_dir` attribute, the Windows path never makes it back to the caller
    unscathed. The value returned from `fetch_home_env ()` is not actually
    used as-is. Instead, the `fetch_account_from_windows ()` method uses it
    to write a pseudo `/etc/passwd`-formatted line that is _then_ parsed via
    the `pwdgrp::parse_passwd ()` method which sees no problem with
    misinterpreting the colon after the drive letter as a field separator of
    that `/etc/passwd`-formatted line, and instead of a Windows path, we now
    have a mere drive letter.
    
    Let's detect when the `HOME` value is still in Windows format in
    `fetch_home_env ()`, and convert it in that case.
    
    For good measure, interpret this "Windows format" not only to include
    absolute paths with drive prefixes, but also UNC paths.
    
    Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

Diff:
---
 winsup/cygwin/uinfo.cc | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 5e2d88bcd7ab..21d729d5dcbc 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -929,7 +929,13 @@ fetch_home_env (void)
   /* If `HOME` is set, prefer it */
   const char *home = getenv ("HOME");
   if (home)
-    return strdup (home);
+    {
+      /* In the very early code path of `user_info::initialize ()`, the value
+         of the environment variable `HOME` is still in its Windows form. */
+      if (isdrive (home) || home[0] == '\\')
+	return (char *) cygwin_create_path (CCP_WIN_A_TO_POSIX, home);
+      return strdup (home);
+    }
 
   /* If `HOME` is unset, fall back to `HOMEDRIVE``HOMEPATH`
      (without a directory separator, as `HOMEPATH` starts with one). */

                 reply	other threads:[~2023-06-06 13:32 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230606133240.40C243858D33@sourceware.org \
    --to=corinna@sourceware.org \
    --cc=cygwin-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).