diff --git a/backport-CVE-2022-29187.patch b/backport-CVE-2022-29187.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3d5e00af4d99e2c49e16688900296c3e1b0bf3d --- /dev/null +++ b/backport-CVE-2022-29187.patch @@ -0,0 +1,163 @@ +From 3b0bf2704980b1ed6018622bdf5377ec22289688 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= +Date: Tue, 10 May 2022 12:35:29 -0700 +Subject: [PATCH] setup: tighten ownership checks post CVE-2022-24765 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +8959555cee7 (setup_git_directory(): add an owner check for the top-level +directory, 2022-03-02), adds a function to check for ownership of +repositories using a directory that is representative of it, and ways to +add exempt a specific repository from said check if needed, but that +check didn't account for owership of the gitdir, or (when used) the +gitfile that points to that gitdir. + +An attacker could create a git repository in a directory that they can +write into but that is owned by the victim to work around the fix that +was introduced with CVE-2022-24765 to potentially run code as the +victim. + +An example that could result in privilege escalation to root in *NIX would +be to set a repository in a shared tmp directory by doing (for example): + + $ git -C /tmp init + +To avoid that, extend the ensure_valid_ownership function to be able to +check for all three paths. + +This will have the side effect of tripling the number of stat() calls +when a repository is detected, but the effect is expected to be likely +minimal, as it is done only once during the directory walk in which Git +looks for a repository. + +Additionally make sure to resolve the gitfile (if one was used) to find +the relevant gitdir for checking. + +While at it change the message printed on failure so it is clear we are +referring to the repository by its worktree (or gitdir if it is bare) and +not to a specific directory. + +Helped-by: Junio C Hamano +Helped-by: Johannes Schindelin +Signed-off-by: Carlo Marcelo Arenas Belón +--- + setup.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 60 insertions(+), 11 deletions(-) + +diff --git a/setup.c b/setup.c +index aad9ace0af97ef..9dcecda65b0a5b 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("ed, 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"), diff --git a/git.spec b/git.spec index 921ca30da75f3a64854bf6d6b5879c2d5ab0e168..20892069db42fabfc92612cec02686c454b503ab 100644 --- a/git.spec +++ b/git.spec @@ -1,7 +1,7 @@ %global gitexecdir %{_libexecdir}/git-core Name: git Version: 2.33.0 -Release: 2 +Release: 3 Summary: A popular and widely used Version Control System License: GPLv2+ or LGPLv2.1 URL: https://git-scm.com/ @@ -19,6 +19,7 @@ Patch3: backport-0004-CVE-2022-24765.patch Patch4: backport-t0033-add-tests-for-safe.directory.patch Patch5: backport-0005-CVE-2022-24765.patch Patch6: backport-0006-CVE-2022-24765.patch +Patch7: backport-CVE-2022-29187.patch BuildRequires: gcc gettext BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre-devel desktop-file-utils @@ -262,6 +263,12 @@ make %{?_smp_mflags} test %{_mandir}/man7/git*.7.* %changelog +* Mon Jul 18 2022 fuanan - 2.33.0-3 +- Type:CVE +- ID:CVE-2022-29187 +- SUG:NA +- DESC:Fix CVE-2022-29187 + * Fri May 20 2022 fuanan - 2.33.0-2 - Type:CVE - ID:CVE-2022-24765