diff mbox series

[v6] git-compat-util: allow root to access both SUDO_UID and root owned

Message ID 20220617202338.27984-1-carenas@gmail.com (mailing list archive)
State New, archived
Headers show
Series [v6] git-compat-util: allow root to access both SUDO_UID and root owned | expand

Commit Message

Carlo Marcelo Arenas Belón June 17, 2022, 8:23 p.m. UTC
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 <Johannes.Schindelin@gmx.de>
Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
---
It is a little more involved than the proposed change just to make
sure that it doesn't introduce any change on behavior (the code is
still strictly only invoked after we confirm process is running as
root) and keeps the documentation and test changes that were in the
original proposal.

A CI run (which is the only way to reliably test this, since the
prerequisite only works in macOS agents like the ones provided by
GitHub) with this patch merged into master is available[1]

[1] https://github.com/carenas/git/actions/runs/2516394052

Changes since v5:
* simplify logic change to avoid additional refactoring

 Documentation/config/safe.txt  |  5 +++--
 git-compat-util.h              |  7 ++++++-
 t/t0034-root-safe-directory.sh | 15 +--------------
 3 files changed, 10 insertions(+), 17 deletions(-)


base-commit: b9063afda17a2aa6310423c9f7b776c41f753091

Comments

Junio C Hamano June 17, 2022, 9:02 p.m. UTC | #1
Carlo Marcelo Arenas Belón  <carenas@gmail.com> writes:

> 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 <Johannes.Schindelin@gmx.de>
> Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
> ---
> It is a little more involved than the proposed change just to make
> sure that it doesn't introduce any change on behavior (the code is
> still strictly only invoked after we confirm process is running as
> root) and keeps the documentation and test changes that were in the
> original proposal.
>
> A CI run (which is the only way to reliably test this, since the
> prerequisite only works in macOS agents like the ones provided by
> GitHub) with this patch merged into master is available[1]
>
> [1] https://github.com/carenas/git/actions/runs/2516394052
>
> Changes since v5:
> * simplify logic change to avoid additional refactoring
>
>  Documentation/config/safe.txt  |  5 +++--
>  git-compat-util.h              |  7 ++++++-
>  t/t0034-root-safe-directory.sh | 15 +--------------
>  3 files changed, 10 insertions(+), 17 deletions(-)
>
> diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt
> index c6ebd1674d..3128b13271 100644
> --- a/Documentation/config/safe.txt
> +++ b/Documentation/config/safe.txt
> @@ -31,11 +31,12 @@ 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

Not a problem with this patch, but one extra space at the beginning
of this line looks funny.  I'd probably remove it while queueing if
I do not forget.

> -and will allow access to the uid recorded as its value instead.
> +and will allow access to the uid recorded as its value in addition to
> +the id from 'root'.

OK.  So the original user who invoked "sudo", plus root.  Does "the
id from root" refer to ROOT_UID?  I am just wondering if "from" is
the right preposition (what the sentence wants to say is perfectly
clear, so the patch is OK as-is, but "user id of 'root'" is probably
what I would have said).

>  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.

OK.  The same escape hatch works, and the code change does not
contribut to any behaviour change in this area, so there is no
reason to change the phrasing here.  I guess they mean the same
thing anyway, so let's take it.

> diff --git a/git-compat-util.h b/git-compat-util.h
> index e7cbfa65c9..f505f817d5 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -447,7 +447,12 @@ static inline int is_path_owned_by_current_uid(const char *path)
>  
>  	euid = geteuid();
>  	if (euid == ROOT_UID)
> -		extract_id_from_env("SUDO_UID", &euid);
> +	{

Style?

-	if (euid == ROOT_UID)
-		extract_id_from_env("SUDO_UID", &euid);
+	if (euid == ROOT_UID) {

> +		if (st.st_uid == ROOT_UID)
> +			return 1;
> +		else
> +			extract_id_from_env("SUDO_UID", &euid);
> +	}
>  
>  	return st.st_uid == euid;
>  }

I would not call it clearer than what Dscho called "something like
this", and

	if (euid == ROOT_UID && st.st_uid != ROOT_UID)
		extract(...);
	return st.st_uid == euid;

would be what I would have written, but they mean the same thing, so
let's take it as-is.

Thanks.
diff mbox series

Patch

diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt
index c6ebd1674d..3128b13271 100644
--- a/Documentation/config/safe.txt
+++ b/Documentation/config/safe.txt
@@ -31,11 +31,12 @@  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.
+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.
diff --git a/git-compat-util.h b/git-compat-util.h
index e7cbfa65c9..f505f817d5 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -447,7 +447,12 @@  static inline int is_path_owned_by_current_uid(const char *path)
 
 	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;
 }
diff --git a/t/t0034-root-safe-directory.sh b/t/t0034-root-safe-directory.sh
index a621f1ea5e..ff31176128 100755
--- a/t/t0034-root-safe-directory.sh
+++ b/t/t0034-root-safe-directory.sh
@@ -68,7 +68,7 @@  test_expect_success 'can access if addressed explicitly' '
 	)
 '
 
-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 with sudo if root by removing SUDO_UID' '
 	)
 '
 
-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