summaryrefslogtreecommitdiff
path: root/setup.c
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2022-06-23 10:35:30 (GMT)
committerJohannes Schindelin <johannes.schindelin@gmx.de>2022-06-23 10:35:30 (GMT)
commitfc0c773028685cdbae35c6c71f3fd3b87ab70985 (patch)
tree28e1948dec2d568d3591fa9f6b1b0e7b87d1a2f0 /setup.c
parent15304344342b7c888f732d28f908890d874bcb0c (diff)
parent5b1c746c352e85211770e5cbd26a433b3affd3b4 (diff)
downloadgit-fc0c773028685cdbae35c6c71f3fd3b87ab70985.zip
git-fc0c773028685cdbae35c6c71f3fd3b87ab70985.tar.gz
git-fc0c773028685cdbae35c6c71f3fd3b87ab70985.tar.bz2
Sync with 2.31.4
* maint-2.31: Git 2.31.4 Git 2.30.5 setup: tighten ownership checks post CVE-2022-24765 git-compat-util: allow root to access both SUDO_UID and root owned t0034: add negative tests and allow git init to mostly work under sudo git-compat-util: avoid failing dir ownership checks if running privileged t: regression git needs safe.directory when using sudo
Diffstat (limited to 'setup.c')
-rw-r--r--setup.c71
1 files changed, 60 insertions, 11 deletions
diff --git a/setup.c b/setup.c
index f4c9a54..8e03228 100644
--- a/setup.c
+++ b/setup.c
@@ -1054,14 +1054,32 @@ static int safe_directory_cb(const char *key, const char *value, void *d)
return 0;
}
-static int ensure_valid_ownership(const char *path)
+/*
+ * Check if a repository is safe, by verifying the ownership of the
+ * worktree (if any), the git directory, and the gitfile (if any).
+ *
+ * Exemptions for known-safe repositories can be added via `safe.directory`
+ * config settings; for non-bare repositories, their worktree needs to be
+ * added, for bare ones their git directory.
+ */
+static int ensure_valid_ownership(const char *gitfile,
+ const char *worktree, const char *gitdir)
{
- struct safe_directory_data data = { .path = path };
+ struct safe_directory_data data = {
+ .path = worktree ? worktree : gitdir
+ };
if (!git_env_bool("GIT_TEST_ASSUME_DIFFERENT_OWNER", 0) &&
- is_path_owned_by_current_user(path))
+ (!gitfile || is_path_owned_by_current_user(gitfile)) &&
+ (!worktree || is_path_owned_by_current_user(worktree)) &&
+ (!gitdir || is_path_owned_by_current_user(gitdir)))
return 1;
+ /*
+ * data.path is the "path" that identifies the repository and it is
+ * constant regardless of what failed above. data.is_safe should be
+ * initialized to false, and might be changed by the callback.
+ */
read_very_early_config(safe_directory_cb, &data);
return data.is_safe;
@@ -1149,6 +1167,8 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
current_device = get_device_or_die(dir->buf, NULL, 0);
for (;;) {
int offset = dir->len, error_code = 0;
+ char *gitdir_path = NULL;
+ char *gitfile = NULL;
if (offset > min_offset)
strbuf_addch(dir, '/');
@@ -1159,21 +1179,50 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
if (die_on_error ||
error_code == READ_GITFILE_ERR_NOT_A_FILE) {
/* NEEDSWORK: fail if .git is not file nor dir */
- if (is_git_directory(dir->buf))
+ if (is_git_directory(dir->buf)) {
gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
+ gitdir_path = xstrdup(dir->buf);
+ }
} else if (error_code != READ_GITFILE_ERR_STAT_FAILED)
return GIT_DIR_INVALID_GITFILE;
- }
+ } else
+ gitfile = xstrdup(dir->buf);
+ /*
+ * Earlier, we tentatively added DEFAULT_GIT_DIR_ENVIRONMENT
+ * to check that directory for a repository.
+ * Now trim that tentative addition away, because we want to
+ * focus on the real directory we are in.
+ */
strbuf_setlen(dir, offset);
if (gitdirenv) {
- if (!ensure_valid_ownership(dir->buf))
- return GIT_DIR_INVALID_OWNERSHIP;
- strbuf_addstr(gitdir, gitdirenv);
- return GIT_DIR_DISCOVERED;
+ enum discovery_result ret;
+
+ if (ensure_valid_ownership(gitfile,
+ dir->buf,
+ (gitdir_path ? gitdir_path : gitdirenv))) {
+ strbuf_addstr(gitdir, gitdirenv);
+ ret = GIT_DIR_DISCOVERED;
+ } else
+ ret = GIT_DIR_INVALID_OWNERSHIP;
+
+ /*
+ * Earlier, during discovery, we might have allocated
+ * string copies for gitdir_path or gitfile so make
+ * sure we don't leak by freeing them now, before
+ * leaving the loop and function.
+ *
+ * Note: gitdirenv will be non-NULL whenever these are
+ * allocated, therefore we need not take care of releasing
+ * them outside of this conditional block.
+ */
+ free(gitdir_path);
+ free(gitfile);
+
+ return ret;
}
if (is_git_directory(dir->buf)) {
- if (!ensure_valid_ownership(dir->buf))
+ if (!ensure_valid_ownership(NULL, NULL, dir->buf))
return GIT_DIR_INVALID_OWNERSHIP;
strbuf_addstr(gitdir, ".");
return GIT_DIR_BARE;
@@ -1306,7 +1355,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
struct strbuf quoted = STRBUF_INIT;
sq_quote_buf_pretty(&quoted, dir.buf);
- die(_("unsafe repository ('%s' is owned by someone else)\n"
+ die(_("detected dubious ownership in repository at '%s'\n"
"To add an exception for this directory, call:\n"
"\n"
"\tgit config --global --add safe.directory %s"),