git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/2] Resolve double chmod() in move_temp_to_file()

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 28, 2009, 06:21 UTC
Message-ID
<7viqlu1837.fsf@gitster.siamese.dyndns.org>
In-Reply-To
<200903261617.48362.johan@herland.net>
Johan Herland <johan@herland.net> writes:
Show 10 quoted lines
> diff --git a/sha1_file.c b/sha1_file.c
> index 87ac53b..05af3c5 100644
> --- a/sha1_file.c
> +++ b/sha1_file.c
> @@ -2252,7 +2252,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
>  		/* FIXME!!! Collision check here ? */
>  	}
>  
> -	if (chmod(filename, 0444) || adjust_shared_perm(filename))
> +	if (chmod(filename, get_shared_perm(0444)))

Your get_shared_perm() will end up feeding 0444 to S_ISDIR(), which would most likely say "no" and cause real harm, but there is no guarantee that we won't start checking S_ISREG() or other things in get_shared_perm() later. I do not like this.

How about doing it this way instead?

One thing to note is that we seem to have been passing what we read from st.st_mode, together with S_IFMT bits, to chmod(2); I do not think I've seen any breakage reports on exotic systems (glibc on Linux seems to ignore the higher bits), but from my reading of POSIX, I would not be surprised if somebody's chmod(2) returned EINVAL.

-- >8 -- set_shared_perm(): sometimes we know what the final mode bits should look like

adjust_shared_perm() first obtains the mode bits from lstat(2), expecting to find what the result of applying user's umask is, and then tweaked it as necessary. When the file to be adjusted is created with mkstemp(3), however, the mode thusly obtained does not have anything to do with usre's umask, and we would need to start from 0444 in such a case and there is no point running lstat(2) for such a path.

This introduces a new API set_shared_perm() to bypass the lstat(2) and instead force setting the mode bits to the desired value directly. adjust_shared_perm() becomes a thin wrapper to the function.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 cache.h     |    3 ++-
 path.c      |   25 ++++++++++++++++---------
 sha1_file.c |    4 ++--
 3 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/cache.h b/cache.h
index 189151d..e283bbe 100644
--- a/cache.h
+++ b/cache.h
@@ -613,7 +613,8 @@ enum sharedrepo {
 	PERM_EVERYBODY      = 0664,
 };
 int git_config_perm(const char *var, const char *value);
-int adjust_shared_perm(const char *path);
+int set_shared_perm(const char *path, int mode);
+#define adjust_shared_perm(path) set_shared_perm((path), 0)
 int safe_create_leading_directories(char *path);
 int safe_create_leading_directories_const(const char *path);
 char *enter_repo(char *path, int strict);
diff --git a/path.c b/path.c
index 42898e0..8a0a674 100644
--- a/path.c
+++ b/path.c
@@ -311,16 +311,23 @@ char *enter_repo(char *path, int strict)
 	return NULL;
 }
 
-int adjust_shared_perm(const char *path)
+int set_shared_perm(const char *path, int mode)
 {
 	struct stat st;
-	int mode, tweak, shared;
+	int tweak, shared, orig_mode;
 
-	if (!shared_repository)
+	if (!shared_repository) {
+		if (mode)
+			return chmod(path, mode & ~S_IFMT);
 		return 0;
-	if (lstat(path, &st) < 0)
-		return -1;
-	mode = st.st_mode;
+	}
+	if (!mode) {
+		if (lstat(path, &st) < 0)
+			return -1;
+		mode = st.st_mode;
+		orig_mode = mode;
+	} else
+		orig_mode = 0;
 	if (shared_repository < 0)
 		shared = -shared_repository;
 	else
@@ -344,9 +351,9 @@ int adjust_shared_perm(const char *path)
 	}
 
 	if (((shared_repository < 0
-	      ? (st.st_mode & (FORCE_DIR_SET_GID | 0777))
-	      : (st.st_mode & mode)) != mode) &&
-	    chmod(path, mode) < 0)
+	      ? (orig_mode & (FORCE_DIR_SET_GID | 0777))
+	      : (orig_mode & mode)) != mode) &&
+	    chmod(path, (mode & ~S_IFMT)) < 0)
 		return -2;
 	return 0;
 }
diff --git a/sha1_file.c b/sha1_file.c
index 8869488..5bfc36c 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2263,7 +2263,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
 	 *
 	 * The same holds for FAT formatted media.
 	 *
-	 * When this succeeds, we just return 0. We have nothing
+	 * When this succeeds, we just return; we have nothing
 	 * left to unlink.
 	 */
 	if (ret && ret != EEXIST) {
@@ -2280,7 +2280,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
 	}
 
 out:
-	if (chmod(filename, 0444) || adjust_shared_perm(filename))
+	if (set_shared_perm(filename, (S_IFREG|0444)))
 		return error("unable to set permission to '%s'", filename);
 	return 0;
 }
Previous: Johan HerlandNext: Johan Herland
Message 28 of 30 in “[BUG?] How to make a shared/restricted repo?”
  1. Johan HerlandMar 25, 2009
  2. Brandon CaseyMar 25, 2009
  3. Johan HerlandMar 25, 2009
  4. Junio C HamanoMar 25, 2009
  5. Junio C HamanoMar 25, 2009
  6. Johan HerlandMar 25, 2009
  7. Junio C HamanoMar 25, 2009
  8. 0/7 Restricting repository access (Was: [BUG?] How to make a shared/restricted repo?)Johan Herland, Mar 25, 2009
  9. 1/7 Clarify documentation on permissions in shared repositoriesJohan Herland, Mar 25, 2009
  10. 2/7 Cleanup: Remove unnecessary if-else clauseJohan Herland, Mar 25, 2009
  11. 3/7 Introduce core.restrictedRepository for restricting repository permissionsJohan Herland, Mar 25, 2009
  12. 4/7 git-init: Introduce --restricted for restricting repository accessJohan Herland, Mar 25, 2009
  13. 5/7 Add tests for "core.restrictedRepository" and "git init --restricted"Johan Herland, Mar 25, 2009
  14. 6/7 git-init: Apply correct mode bits to template files in shared/restricted repoJohan Herland, Mar 25, 2009
  15. 7/7 Apply restricted permissions to loose objects and pack filesJohan Herland, Mar 25, 2009
  16. Junio C HamanoMar 25, 2009
  17. Johan HerlandMar 26, 2009
  18. Junio C HamanoMar 26, 2009
  19. Johan HerlandMar 26, 2009
  20. Johannes SixtMar 26, 2009
  21. Johan HerlandMar 26, 2009
  22. Johannes SixtMar 26, 2009
  23. 0/2 chmod cleanup (Was: [BUG?] How to make a shared/restricted repo?)Johan Herland, Mar 26, 2009
  24. 1/2 Move chmod(foo, 0444) into move_temp_to_file()Johan Herland, Mar 26, 2009
  25. Junio C HamanoMar 28, 2009
  26. Johan HerlandMar 28, 2009
  27. 2/2 Resolve double chmod() in move_temp_to_file()Johan Herland, Mar 26, 2009
  28. Junio C HamanoMar 28, 2009
  29. Johan HerlandMar 28, 2009
  30. Junio C HamanoMar 29, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.