diff -Nru git-2.25.1/debian/changelog git-2.25.1/debian/changelog --- git-2.25.1/debian/changelog 2022-04-25 23:21:34.000000000 +0000 +++ git-2.25.1/debian/changelog 2022-07-05 15:13:30.000000000 +0000 @@ -1,3 +1,26 @@ +git (1:2.25.1-1ubuntu3.5) focal-security; urgency=medium + + * SECURITY UPDATE: Potential arbitrary code execution + - debian/patches/CVE-2022-29187-1.patch: adds test to + regression git needs safe.directory when using sudo in + t/t0034-root-safe-directory.sh. + - debian/patches/CVE-2022-29187-2.patch: avoid failing dir ownership + checks if running privileged in git-compat-util.h, + t/t0034-root-safe-directory.sh. + - debian/patches/CVE-2022-29187-3.patch: add negative tests + and allow git init to mostly work under sudo in + t/lib-sudo.sh b/t/lib-sudo.sh. + - debian/patches/CVE-2022-29187-4.patch: allow root + to access both SUDO_UID and root owned in git-compat-util.h, + t/t0034-root-safe-directory.sh. + - debian/patches/CVE-2022-29187-5.patch: add tests for safe.directory + in t/t0033-safe-directory.sh, setup.c. + - debian/patches/CVE-2022-29187-6.patch: tighten ownership checks + post CVE-2022-24765 in setup.c. + - CVE-2022-29187 + + -- Leonidas Da Silva Barbosa Tue, 05 Jul 2022 12:13:30 -0300 + git (1:2.25.1-1ubuntu3.4) focal-security; urgency=medium * SECURITY REGRESSION: Previous update was incomplete causing regressions diff -Nru git-2.25.1/debian/patches/CVE-2022-29187-1.patch git-2.25.1/debian/patches/CVE-2022-29187-1.patch --- git-2.25.1/debian/patches/CVE-2022-29187-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-2.25.1/debian/patches/CVE-2022-29187-1.patch 2022-07-05 15:12:11.000000000 +0000 @@ -0,0 +1,136 @@ +From 5f1a3fec8c304decaa9af2bf503712050a4a84e0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= +Date: Thu, 12 May 2022 18:00:17 -0700 +Subject: [PATCH 2/7] t: regression git needs safe.directory when using sudo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Originally reported after release of v2.35.2 (and other maint branches) +for CVE-2022-24765 and blocking otherwise harmless commands that were +done using sudo in a repository that was owned by the user. + +Add a new test script with very basic support to allow running git +commands through sudo, so a reproduction could be implemented and that +uses only `git status` as a proxy of the issue reported. + +Note that because of the way sudo interacts with the system, a much +more complete integration with the test framework will require a lot +more work and that was therefore intentionally punted for now. + +The current implementation requires the execution of a special cleanup +function which should always be kept as the last "test" or otherwise +the standard cleanup functions will fail because they can't remove +the root owned directories that are used. This also means that if +failures are found while running, the specifics of the failure might +not be kept for further debugging and if the test was interrupted, it +will be necessary to clean the working directory manually before +restarting by running: + + $ sudo rm -rf trash\ directory.t0034-root-safe-directory/ + +The test file also uses at least one initial "setup" test that creates +a parallel execution directory under the "root" sub directory, which +should be used as top level directory for all repositories that are +used in this test file. Unlike all other tests the repository provided +by the test framework should go unused. + +Special care should be taken when invoking commands through sudo, since +the environment is otherwise independent from what the test framework +setup and might have changed the values for HOME, SHELL and dropped +several relevant environment variables for your test. Indeed `git status` +was used as a proxy because it doesn't even require commits in the +repository to work and usually doesn't require much from the environment +to run, but a future patch will add calls to `git init` and that will +fail to honor the default branch name, unless that setting is NOT +provided through an environment variable (which means even a CI run +could fail that test if enabled incorrectly). + +A new SUDO prerequisite is provided that does some sanity checking +to make sure the sudo command that will be used allows for passwordless +execution as root without restrictions and doesn't mess with git's +execution path. This matches what is provided by the macOS agents that +are used as part of GitHub actions and probably nowhere else. + +Most of those characteristics make this test mostly only suitable for +CI, but it might be executed locally if special care is taken to provide +for all of them in the local configuration and maybe making use of the +sudo credential cache by first invoking sudo, entering your password if +needed, and then invoking the test with: + + $ GIT_TEST_ALLOW_SUDO=YES ./t0034-root-safe-directory.sh + +If it fails to run, then it means your local setup wouldn't work for the +test because of the configuration sudo has or other system settings, and +things that might help are to comment out sudo's secure_path config, and +make sure that the account you are using has no restrictions on the +commands it can run through sudo, just like is provided for the user in +the CI. + +For example (assuming a username of marta for you) something probably +similar to the following entry in your /etc/sudoers (or equivalent) file: + + marta ALL=(ALL:ALL) NOPASSWD: ALL + +Reported-by: SZEDER Gábor +Helped-by: Phillip Wood +Signed-off-by: Carlo Marcelo Arenas Belón +Signed-off-by: Junio C Hamano +--- + t/t0034-root-safe-directory.sh | 44 ++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + create mode 100755 t/t0034-root-safe-directory.sh + +diff --git a/t/t0034-root-safe-directory.sh b/t/t0034-root-safe-directory.sh +new file mode 100755 +index 0000000000..f6a5d63ff4 +--- /dev/null ++++ b/t/t0034-root-safe-directory.sh +@@ -0,0 +1,44 @@ ++#!/bin/sh ++ ++test_description='verify safe.directory checks while running as root' ++ ++. ./test-lib.sh ++ ++if [ "$GIT_TEST_ALLOW_SUDO" != "YES" ] ++then ++ skip_all="You must set env var GIT_TEST_ALLOW_SUDO=YES in order to run this test" ++ test_done ++fi ++ ++test_lazy_prereq SUDO ' ++ sudo -n id -u >u && ++ id -u root >r && ++ test_cmp u r && ++ command -v git >u && ++ sudo command -v git >r && ++ test_cmp u r ++' ++ ++test_expect_success SUDO 'setup' ' ++ sudo rm -rf root && ++ mkdir -p root/r && ++ ( ++ cd root/r && ++ git init ++ ) ++' ++ ++test_expect_failure SUDO 'sudo git status as original owner' ' ++ ( ++ cd root/r && ++ git status && ++ sudo git status ++ ) ++' ++ ++# this MUST be always the last test ++test_expect_success SUDO 'cleanup' ' ++ sudo rm -rf root ++' ++ ++test_done +-- +2.25.1 + diff -Nru git-2.25.1/debian/patches/CVE-2022-29187-2.patch git-2.25.1/debian/patches/CVE-2022-29187-2.patch --- git-2.25.1/debian/patches/CVE-2022-29187-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-2.25.1/debian/patches/CVE-2022-29187-2.patch 2022-07-05 15:12:24.000000000 +0000 @@ -0,0 +1,158 @@ +From ae9abbb63eea74441e3e8b153dc6ec1f94c373b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= +Date: Thu, 12 May 2022 18:00:18 -0700 +Subject: [PATCH 3/7] git-compat-util: avoid failing dir ownership checks if + running privileged +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +bdc77d1d685 (Add a function to determine whether a path is owned by the +current user, 2022-03-02) checks for the effective uid of the running +process using geteuid() but didn't account for cases where that user was +root (because git was invoked through sudo or a compatible tool) and the +original uid that repository trusted for its config was no longer known, +therefore failing the following otherwise safe call: + + guy@renard ~/Software/uncrustify $ sudo git describe --always --dirty + [sudo] password for guy: + fatal: unsafe repository ('/home/guy/Software/uncrustify' is owned by someone else) + +Attempt to detect those cases by using the environment variables that +those tools create to keep track of the original user id, and do the +ownership check using that instead. + +This assumes the environment the user is running on after going +privileged can't be tampered with, and also adds code to restrict that +the new behavior only applies if running as root, therefore keeping the +most common case, which runs unprivileged, from changing, but because of +that, it will miss cases where sudo (or an equivalent) was used to change +to another unprivileged user or where the equivalent tool used to raise +privileges didn't track the original id in a sudo compatible way. + +Because of compatibility with sudo, the code assumes that uid_t is an +unsigned integer type (which is not required by the standard) but is used +that way in their codebase to generate SUDO_UID. In systems where uid_t +is signed, sudo might be also patched to NOT be unsigned and that might +be able to trigger an edge case and a bug (as described in the code), but +it is considered unlikely to happen and even if it does, the code would +just mostly fail safely, so there was no attempt either to detect it or +prevent it by the code, which is something that might change in the future, +based on expected user feedback. + +Reported-by: Guy Maurel +Helped-by: SZEDER Gábor +Helped-by: Randall Becker +Helped-by: Phillip Wood +Suggested-by: Johannes Schindelin +Signed-off-by: Carlo Marcelo Arenas Belón +Signed-off-by: Junio C Hamano +--- + Documentation/config/safe.txt | 13 +++++++++ + git-compat-util.h | 53 +++++++++++++++++++++++++++++++++- + t/t0034-root-safe-directory.sh | 2 +- + 3 files changed, 66 insertions(+), 2 deletions(-) + +Index: git-2.25.1/Documentation/config/safe.txt +=================================================================== +--- git-2.25.1.orig/Documentation/config/safe.txt ++++ git-2.25.1/Documentation/config/safe.txt +@@ -26,3 +26,16 @@ directory was listed in the `safe.direct + is set in system config and you want to re-enable this protection, then + initialize your list with an empty value before listing the repositories + that you deem safe. +++ ++As explained, Git only allows you to access repositories owned by ++yourself, i.e. the user who is running Git, by default. When Git ++is running as 'root' in a non Windows platform that provides sudo, ++ however, git checks the SUDO_UID environment variable that sudo creates ++and will allow access to the uid recorded as its value instead. ++This is to make it easy to perform a common sequence during installation ++"make && sudo make install". A git process running under 'sudo' runs as ++'root' but the 'sudo' command exports the environment variable to record ++which id the original user has. ++If that is not what you would prefer and want git to only trust ++repositories that are owned by root instead, then you must remove ++the `SUDO_UID` variable from root's environment before invoking git. +Index: git-2.25.1/git-compat-util.h +=================================================================== +--- git-2.25.1.orig/git-compat-util.h ++++ git-2.25.1/git-compat-util.h +@@ -389,12 +389,63 @@ static inline int git_offset_1st_compone + #endif + + #ifndef is_path_owned_by_current_user ++ ++#ifdef __TANDEM ++#define ROOT_UID 65535 ++#else ++#define ROOT_UID 0 ++#endif ++ ++/* ++ * Do not use this function when ++ * (1) geteuid() did not say we are running as 'root', or ++ * (2) using this function will compromise the system. ++ * ++ * PORTABILITY WARNING: ++ * This code assumes uid_t is unsigned because that is what sudo does. ++ * If your uid_t type is signed and all your ids are positive then it ++ * should all work fine. ++ * If your version of sudo uses negative values for uid_t or it is ++ * buggy and return an overflowed value in SUDO_UID, then git might ++ * fail to grant access to your repository properly or even mistakenly ++ * grant access to someone else. ++ * In the unlikely scenario this happened to you, and that is how you ++ * got to this message, we would like to know about it; so sent us an ++ * email to git@vger.kernel.org indicating which platform you are ++ * using and which version of sudo, so we can improve this logic and ++ * maybe provide you with a patch that would prevent this issue again ++ * in the future. ++ */ ++static inline void extract_id_from_env(const char *env, uid_t *id) ++{ ++ const char *real_uid = getenv(env); ++ ++ /* discard anything empty to avoid a more complex check below */ ++ if (real_uid && *real_uid) { ++ char *endptr = NULL; ++ unsigned long env_id; ++ ++ errno = 0; ++ /* silent overflow errors could trigger a bug here */ ++ env_id = strtoul(real_uid, &endptr, 10); ++ if (!*endptr && !errno) ++ *id = env_id; ++ } ++} ++ + static inline int is_path_owned_by_current_uid(const char *path) + { + struct stat st; ++ uid_t euid; ++ + if (lstat(path, &st)) + return 0; +- return st.st_uid == geteuid(); ++ ++ euid = geteuid(); ++ if (euid == ROOT_UID) ++ extract_id_from_env("SUDO_UID", &euid); ++ ++ return st.st_uid == euid; + } + + #define is_path_owned_by_current_user is_path_owned_by_current_uid +Index: git-2.25.1/t/t0034-root-safe-directory.sh +=================================================================== +--- git-2.25.1.orig/t/t0034-root-safe-directory.sh ++++ git-2.25.1/t/t0034-root-safe-directory.sh +@@ -28,7 +28,7 @@ test_expect_success SUDO 'setup' ' + ) + ' + +-test_expect_failure SUDO 'sudo git status as original owner' ' ++test_expect_success SUDO 'sudo git status as original owner' ' + ( + cd root/r && + git status && diff -Nru git-2.25.1/debian/patches/CVE-2022-29187-3.patch git-2.25.1/debian/patches/CVE-2022-29187-3.patch --- git-2.25.1/debian/patches/CVE-2022-29187-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-2.25.1/debian/patches/CVE-2022-29187-3.patch 2022-07-05 15:12:42.000000000 +0000 @@ -0,0 +1,155 @@ +From b9063afda17a2aa6310423c9f7b776c41f753091 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= +Date: Thu, 12 May 2022 18:00:19 -0700 +Subject: [PATCH 4/7] t0034: add negative tests and allow git init to mostly + work under sudo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a support library that provides one function that can be used +to run a "scriplet" of commands through sudo and that helps invoking +sudo in the slightly awkward way that is required to ensure it doesn't +block the call (if shell was allowed as tested in the prerequisite) +and it doesn't run the command through a different shell than the one +we intended. + +Add additional negative tests as suggested by Junio and that use a +new workspace that is owned by root. + +Document a regression that was introduced by previous commits where +root won't be able anymore to access directories they own unless +SUDO_UID is removed from their environment. + +The tests document additional ways that this new restriction could +be worked around and the documentation explains why it might be instead +considered a feature, but a "fix" is planned for a future change. + +Helped-by: Junio C Hamano +Helped-by: Phillip Wood +Signed-off-by: Carlo Marcelo Arenas Belón +Signed-off-by: Junio C Hamano +--- + t/lib-sudo.sh | 15 ++++++++ + t/t0034-root-safe-directory.sh | 62 ++++++++++++++++++++++++++++++++++ + 2 files changed, 77 insertions(+) + create mode 100644 t/lib-sudo.sh + +diff --git a/t/lib-sudo.sh b/t/lib-sudo.sh +new file mode 100644 +index 0000000000..b4d7788f4e +--- /dev/null ++++ b/t/lib-sudo.sh +@@ -0,0 +1,15 @@ ++# Helpers for running git commands under sudo. ++ ++# Runs a scriplet passed through stdin under sudo. ++run_with_sudo () { ++ local ret ++ local RUN="$TEST_DIRECTORY/$$.sh" ++ write_script "$RUN" "$TEST_SHELL_PATH" ++ # avoid calling "$RUN" directly so sudo doesn't get a chance to ++ # override the shell, add aditional restrictions or even reject ++ # running the script because its security policy deem it unsafe ++ sudo "$TEST_SHELL_PATH" -c "\"$RUN\"" ++ ret=$? ++ rm -f "$RUN" ++ return $ret ++} +diff --git a/t/t0034-root-safe-directory.sh b/t/t0034-root-safe-directory.sh +index 6b8ea5357f..a621f1ea5e 100755 +--- a/t/t0034-root-safe-directory.sh ++++ b/t/t0034-root-safe-directory.sh +@@ -3,6 +3,7 @@ + test_description='verify safe.directory checks while running as root' + + . ./test-lib.sh ++. "$TEST_DIRECTORY"/lib-sudo.sh + + if [ "$GIT_TEST_ALLOW_SUDO" != "YES" ] + then +@@ -10,6 +11,12 @@ then + test_done + fi + ++if ! test_have_prereq NOT_ROOT ++then ++ skip_all="These tests do not support running as root" ++ test_done ++fi ++ + test_lazy_prereq SUDO ' + sudo -n id -u >u && + id -u root >r && +@@ -19,6 +26,12 @@ test_lazy_prereq SUDO ' + test_cmp u r + ' + ++if ! test_have_prereq SUDO ++then ++ skip_all="Your sudo/system configuration is either too strict or unsupported" ++ test_done ++fi ++ + test_expect_success SUDO 'setup' ' + sudo rm -rf root && + mkdir -p root/r && +@@ -36,6 +49,55 @@ test_expect_success SUDO 'sudo git status as original owner' ' + ) + ' + ++test_expect_success SUDO 'setup root owned repository' ' ++ sudo mkdir -p root/p && ++ sudo git init root/p ++' ++ ++test_expect_success 'cannot access if owned by root' ' ++ ( ++ cd root/p && ++ test_must_fail git status ++ ) ++' ++ ++test_expect_success 'can access if addressed explicitly' ' ++ ( ++ cd root/p && ++ GIT_DIR=.git GIT_WORK_TREE=. git status ++ ) ++' ++ ++test_expect_failure SUDO 'can access with sudo if root' ' ++ ( ++ cd root/p && ++ sudo git status ++ ) ++' ++ ++test_expect_success SUDO 'can access with sudo if root by removing SUDO_UID' ' ++ ( ++ cd root/p && ++ run_with_sudo <<-END ++ unset SUDO_UID && ++ git status ++ END ++ ) ++' ++ ++test_lazy_prereq SUDO_SUDO ' ++ sudo sudo id -u >u && ++ id -u root >r && ++ test_cmp u r ++' ++ ++test_expect_success SUDO_SUDO 'can access with sudo abusing SUDO_UID' ' ++ ( ++ cd root/p && ++ sudo sudo git status ++ ) ++' ++ + # this MUST be always the last test + test_expect_success SUDO 'cleanup' ' + sudo rm -rf root +-- +2.25.1 + diff -Nru git-2.25.1/debian/patches/CVE-2022-29187-4.patch git-2.25.1/debian/patches/CVE-2022-29187-4.patch --- git-2.25.1/debian/patches/CVE-2022-29187-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-2.25.1/debian/patches/CVE-2022-29187-4.patch 2022-07-05 15:12:57.000000000 +0000 @@ -0,0 +1,102 @@ +From 6b11e3d52e919cce91011f4f9025e6f4b61375f2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= +Date: Fri, 17 Jun 2022 13:23:38 -0700 +Subject: [PATCH 5/7] git-compat-util: allow root to access both SUDO_UID and + root owned +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Previous changes introduced a regression which will prevent root for +accessing repositories owned by thyself if using sudo because SUDO_UID +takes precedence. + +Loosen that restriction by allowing root to access repositories owned +by both uid by default and without having to add a safe.directory +exception. + +A previous workaround that was documented in the tests is no longer +needed so it has been removed together with its specially crafted +prerequisite. + +Helped-by: Johanness Schindelin +Signed-off-by: Carlo Marcelo Arenas Belón +Signed-off-by: Junio C Hamano +--- + Documentation/config/safe.txt | 7 ++++--- + git-compat-util.h | 7 ++++++- + t/t0034-root-safe-directory.sh | 15 +-------------- + 3 files changed, 11 insertions(+), 18 deletions(-) + +Index: git-2.25.1/Documentation/config/safe.txt +=================================================================== +--- git-2.25.1.orig/Documentation/config/safe.txt ++++ git-2.25.1/Documentation/config/safe.txt +@@ -30,12 +30,13 @@ that you deem safe. + As explained, Git only allows you to access repositories owned by + yourself, i.e. the user who is running Git, by default. When Git + is running as 'root' in a non Windows platform that provides sudo, +- however, git checks the SUDO_UID environment variable that sudo creates +-and will allow access to the uid recorded as its value instead. ++however, git checks the SUDO_UID environment variable that sudo creates ++and will allow access to the uid recorded as its value in addition to ++the id from 'root'. + This is to make it easy to perform a common sequence during installation + "make && sudo make install". A git process running under 'sudo' runs as + 'root' but the 'sudo' command exports the environment variable to record + which id the original user has. + If that is not what you would prefer and want git to only trust +-repositories that are owned by root instead, then you must remove ++repositories that are owned by root instead, then you can remove + the `SUDO_UID` variable from root's environment before invoking git. +Index: git-2.25.1/git-compat-util.h +=================================================================== +--- git-2.25.1.orig/git-compat-util.h ++++ git-2.25.1/git-compat-util.h +@@ -443,7 +443,12 @@ static inline int is_path_owned_by_curre + + euid = geteuid(); + if (euid == ROOT_UID) +- extract_id_from_env("SUDO_UID", &euid); ++ { ++ if (st.st_uid == ROOT_UID) ++ return 1; ++ else ++ extract_id_from_env("SUDO_UID", &euid); ++ } + + return st.st_uid == euid; + } +Index: git-2.25.1/t/t0034-root-safe-directory.sh +=================================================================== +--- git-2.25.1.orig/t/t0034-root-safe-directory.sh ++++ git-2.25.1/t/t0034-root-safe-directory.sh +@@ -68,7 +68,7 @@ test_expect_success 'can access if addre + ) + ' + +-test_expect_failure SUDO 'can access with sudo if root' ' ++test_expect_success SUDO 'can access with sudo if root' ' + ( + cd root/p && + sudo git status +@@ -85,19 +85,6 @@ test_expect_success SUDO 'can access wit + ) + ' + +-test_lazy_prereq SUDO_SUDO ' +- sudo sudo id -u >u && +- id -u root >r && +- test_cmp u r +-' +- +-test_expect_success SUDO_SUDO 'can access with sudo abusing SUDO_UID' ' +- ( +- cd root/p && +- sudo sudo git status +- ) +-' +- + # this MUST be always the last test + test_expect_success SUDO 'cleanup' ' + sudo rm -rf root diff -Nru git-2.25.1/debian/patches/CVE-2022-29187-5.patch git-2.25.1/debian/patches/CVE-2022-29187-5.patch --- git-2.25.1/debian/patches/CVE-2022-29187-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-2.25.1/debian/patches/CVE-2022-29187-5.patch 2022-07-05 15:13:04.000000000 +0000 @@ -0,0 +1,68 @@ +From ae4c9a5c9c7e01825b7a7d28aaecaf8790dbc6dd Mon Sep 17 00:00:00 2001 +From: "Leonidas S. Barbosa" +Date: Tue, 5 Jul 2022 10:45:34 -0300 +Subject: [PATCH] test perm + +--- + setup.c | 3 ++- + t/t0033-safe-directory.sh | 34 ++++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 1 deletion(-) + create mode 100755 t/t0033-safe-directory.sh + +diff --git a/setup.c b/setup.c +index 62ce6e9..a9161ac 100644 +--- a/setup.c ++++ b/setup.c +@@ -1059,7 +1059,8 @@ static int ensure_valid_ownership(const char *path) + { + struct safe_directory_data data = { .path = path }; + +- if (is_path_owned_by_current_user(path)) ++ if (!git_env_bool("GIT_TEST_ASSUME_DIFFERENT_OWNER", 0) && ++ is_path_owned_by_current_user(path)) + return 1; + + read_very_early_config(safe_directory_cb, &data); +diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh +new file mode 100755 +index 0000000..9380ff3 +--- /dev/null ++++ b/t/t0033-safe-directory.sh +@@ -0,0 +1,34 @@ ++#!/bin/sh ++ ++test_description='verify safe.directory checks' ++ ++. ./test-lib.sh ++ ++GIT_TEST_ASSUME_DIFFERENT_OWNER=1 ++export GIT_TEST_ASSUME_DIFFERENT_OWNER ++ ++expect_rejected_dir () { ++ test_must_fail git status 2>err && ++ grep "safe.directory" err ++} ++ ++test_expect_success 'safe.directory is not set' ' ++ expect_rejected_dir ++' ++ ++test_expect_success 'safe.directory does not match' ' ++ git config --global safe.directory bogus && ++ expect_rejected_dir ++' ++ ++test_expect_success 'safe.directory matches' ' ++ git config --global --add safe.directory "$(pwd)" && ++ git status ++' ++ ++test_expect_success 'safe.directory matches, but is reset' ' ++ git config --global --add safe.directory "" && ++ expect_rejected_dir ++' ++ ++test_done +-- +2.25.1 + diff -Nru git-2.25.1/debian/patches/CVE-2022-29187-6.patch git-2.25.1/debian/patches/CVE-2022-29187-6.patch --- git-2.25.1/debian/patches/CVE-2022-29187-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-2.25.1/debian/patches/CVE-2022-29187-6.patch 2022-07-05 15:13:23.000000000 +0000 @@ -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 6/7] 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(-) + +Index: git-2.25.1/setup.c +=================================================================== +--- git-2.25.1.orig/setup.c ++++ git-2.25.1/setup.c +@@ -919,14 +919,32 @@ static int safe_directory_cb(const char + 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; +@@ -1014,6 +1032,8 @@ static enum discovery_result setup_git_d + 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, '/'); +@@ -1024,21 +1044,50 @@ static enum discovery_result setup_git_d + 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; +@@ -1171,7 +1220,7 @@ const char *setup_git_directory_gently(i + 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 -Nru git-2.25.1/debian/patches/series git-2.25.1/debian/patches/series --- git-2.25.1/debian/patches/series 2022-04-25 23:21:34.000000000 +0000 +++ git-2.25.1/debian/patches/series 2022-07-05 15:13:19.000000000 +0000 @@ -19,3 +19,9 @@ CVE-2022-24765-4.patch CVE-2022-24765-5.patch CVE-2022-24765-6.patch +CVE-2022-29187-1.patch +CVE-2022-29187-2.patch +CVE-2022-29187-3.patch +CVE-2022-29187-4.patch +CVE-2022-29187-5.patch +CVE-2022-29187-6.patch