summaryrefslogtreecommitdiff
path: root/setup.c
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2022-06-23 10:35:38 (GMT)
committerJohannes Schindelin <johannes.schindelin@gmx.de>2022-06-23 10:35:38 (GMT)
commiteebfde3f213e2990727a64da0d7d04ad961a28b0 (patch)
tree9468049a96ace68b97180e547f2d503c6c9f14ca /setup.c
parent1f65dd6ae635f77c588ac432cad1a299723d00d6 (diff)
parent656d9a24f624039831bc2e865f4cc42f393caf70 (diff)
downloadgit-eebfde3f213e2990727a64da0d7d04ad961a28b0.zip
git-eebfde3f213e2990727a64da0d7d04ad961a28b0.tar.gz
git-eebfde3f213e2990727a64da0d7d04ad961a28b0.tar.bz2
Sync with 2.32.3
* maint-2.32: Git 2.32.3 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 a9161ac..114d9ee 100644
--- a/setup.c
+++ b/setup.c
@@ -1055,14 +1055,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;
@@ -1150,6 +1168,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, '/');
@@ -1160,21 +1180,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;
@@ -1312,7 +1361,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"),