[PATCH v3] setup: don't die if realpath(3) fails on getcwd(3)
- From
Kevin Locke <kevin@kevinlocke.name>
- Date
- May 24, 2022, 14:51 UTC
- Message-ID
- <68c66aef7ca4dba53faec9e6d2f3b70fe58ac33e.1653403877.git.kevin@kevinlocke.name>
- In-Reply-To
- <7c064f43ed426c9e3b54e1ae5313d6b9332a47cb.1653141169.git.kevin@kevinlocke.name>
Prior to Git 2.35.0, git could be run from an inaccessible working directory so long as the git repository specified by options and/or environment variables was accessible. For example:
git init repo
mkdir -p a/b
cd a/b
chmod u-x ..
git -C "${PWD%/a/b}/repo" statusIf this example seems a bit contrived, consider running with the repository owner as a substitute UID (e.g. with runuser(1) or sudo(8)) without ensuring the working directory is accessible by that user.
The code added by e6f8861bd4 ("setup: introduce startup_info->original_cwd") to preserve the working directory attempts to normalize the path using strbuf_realpath(). If that fails, as in the case above, it is treated as a fatal error.
This commit treats strbuf_realpath() errors as non-fatal. If an error occurs, setup_original_cwd() will continue without applying removal prevention for cwd, resulting in the pre-2.35.0 behavior. The risk should be minimal, since git will not operate on a repository with inaccessible ancestors, this behavior is only known to occur when cwd is a descendant of the repository, an ancestor of cwd is inaccessible, and no ancestors of the repository are inaccessible.
Signed-off-by: Kevin Locke <kevin@kevinlocke.name> ---
Notes: Changes since v2: * Use trace2_data_string(), rather than trace_printf(), to report realpath failure.
Changes since v1: * Set startup_info->original_cwd = NULL when strbuf_realpath() fails, rather than setting it to the un-normalized path. * Add a trace message when realpath fails to aid debugging. * Remove potential realpath failure cause from comment before it. * Improve format for reference to e6f8861bd4 in commit message. * Clarify when the pre-2.35.0 behavior may occur as a result of this commit in the commit message. * Remove 'Fixes:' tag from commit message.
setup.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/setup.c b/setup.c index a7b36f3ffbf..38bd55cbac1 100644 --- a/setup.c +++ b/setup.c @@ -458,11 +458,19 @@ static void setup_original_cwd(void) * not startup_info->original_cwd. */ - /* Normalize the directory */ - strbuf_realpath(&tmp, tmp_original_cwd, 1); - free((char*)tmp_original_cwd); - tmp_original_cwd = NULL; - startup_info->original_cwd = strbuf_detach(&tmp, NULL); + /* Try to normalize the directory. */ + if (strbuf_realpath(&tmp, tmp_original_cwd, 0)) { + free((char*)tmp_original_cwd); + tmp_original_cwd = NULL; + startup_info->original_cwd = strbuf_detach(&tmp, NULL); + } else { + trace2_data_string("setup", the_repository, + "realpath-path", tmp_original_cwd); + trace2_data_string("setup", the_repository, + "realpath-failure", strerror(errno)); + tmp_original_cwd = NULL; + goto no_prevention_needed; + } /* * Get our worktree; we only protect the current working directory
-- 2.35.1