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

Re: [PATCH] fetch: allow running as different users in shared repositories

From
Junio C Hamano <gitster@pobox.com>
Date
May 4, 2020, 20:39 UTC
Message-ID
<xmqqlfm7fn8k.fsf@gitster.c.googlers.com>
In-Reply-To
<E1jVeWV-0006Sj-JC@smtp.tt-solutions.com>
Vadim Zeitlin <vz-git@zeitlins.org> writes:
> From: Vadim Zeitlin <vz-git@zeitlins.org>
> Subject: [PATCH] fetch: allow running as different users in shared repositories
This pretends the change to affect ONLY "git fetch", but ...
Show 5 quoted lines
> The function fopen_for_writing(), which was added in 79d7582e32 (commit:
> allow editing the commit message even in shared repos, 2016-01-06) and
> used for overwriting FETCH_HEAD since ea56518dfe (Handle more file
> writes correctly in shared repos, 2016-01-11), didn't do it correctly in
> shared repositories under Linux.

... fopen_for_writing() is not only about FETCH_HEAD. In fact, the author of this patch knows "git fetch" was not the primary target.

So, we need to make sure that (1) this change is beneficial to those other codepaths that use the helper function, and (2) describe the (good) effect of the patch on these other users in the log message. We also need to retitle the commit.

Hits from "git grep fopen_for_writing" are
builtin/commit.c:812:	s->fp = fopen_for_writing(git_path_commit_editmsg());
That's .git/COMMIT_EDITMSG file.
builtin/fast-export.c:1049:	f = fopen_for_writing(file);
This is inside export_marks() to create the marks file.
builtin/fetch.c:1191:	FILE *fp = fopen_for_writing(filename);
This is the .git/FETCH_HEAD.
> This happened because in this situation the file FETCH_HEAD has mode 644
> and attempting to overwrite it when running git-fetch under an account
> different from the one that was had originally created it, failed with
> EACCES, and not EPERM.

Isn't that because FETCH_HEAD and others are not concluded with adjust_shared_perm()? The fopen_for_writing() that removes and recreates the target file sounds like a band-aid to me. The right fix we should have done when we did 79d7582e (commit: allow editing the commit message even in shared repos, 2016-01-06) would have been to open(2) with 0666 (and let the umask(2) adjust it), and then use adjust_shared_perm() to give it the desired protection bits. With the existing band-aid, we won't be able to fix incorrectly created append-only files, for example, as the band-aid depends on the contents in the existing file being expendable.

Having said all that, I agree that EACCES is the right errno to detect for this band-aid, at least for FETCH_HEAD.

I think COMMIT_EDITMSG is also left after "git commit" finishes, so it will share the same issue with FETCH_HEAD and the same fix should apply (this is just a hint for you to write an updated proposed log message for the patch).

I haven't looked at or analysed how fast-export will get affected. I think it is used to create and leave a "marks" file, to be later read by another instance of the fast-export process, which may (or may not) further write new contents to the (same?) "marks" file, but I do not know the ramifications of unlinking and recreating. In any case, even if that is broken, it is not a new breakage this patch is introducing. You may want to look at it further to make sure you are not breaking things, though.

So, here are the things I would like to see in this area:
 - The same patch text, but with updated commit log message, to tell
   readers that we have looked at all the callers that are affected,
   and retitle it (e.g. "fopen_for_writing: detect the reason why fopen()
   failed correctly" or something like that, perhaps?).
   
 - Audit other codepaths that create .git/ALL_CAPS_FILE (e.g.  I see
   that "git branch --edit-description" creates a temporary file to
   edit without fopen_for_writing() band-aid and it does not use
   adjust_shared_perm(), but I think it should) and fix them.
 - The existing repositories have these files created and left whose
   permission bits were set according to the then-current umask
   without taking "core.sharedrepository" into account, so we have
   to keep the "if unable to open for writing, unlink and recreate"
   trick to salvage them.  But it does not mean we need to keep
   creating the files with wrong mode.  Update fopen_for_writing()
   and its users to leave the file created in the right mode by
   calling adjust_shared_perm().  I think fopen_for_writing() should
   switch from calling fopen(3) to calling open(2) and then fdopen(3)
   on the result as the first step.

The first one is better done by you to tie the loose ends for this discussion.

Other two items do not have to be done by you. Anybody interested can do them as a clean-up (only if people agree that it is a good idea to do so---so I won't mark this as a left-over-bits yet).

Thanks.
Show 19 quoted lines
> diff --git a/wrapper.c b/wrapper.c
> index e1eaef2e16..f5607241da 100644
> --- a/wrapper.c
> +++ b/wrapper.c
> @@ -373,11 +373,12 @@ FILE *fopen_for_writing(const char *path)
>  {
>  	FILE *ret = fopen(path, "w");
>  
> -	if (!ret && errno == EPERM) {
> +	if (!ret && (errno == EACCES || errno == EPERM)) {
> +		int open_error = errno;
>  		if (!unlink(path))
>  			ret = fopen(path, "w");
>  		else
> -			errno = EPERM;
> +			errno = open_error;
>  	}
>  	return ret;
>  }
Previous: Vadim ZeitlinNext: Vadim Zeitlin
Message 7 of 8 in “Re: [PATCH] fetch: allow running as different users in shared repositories”
  1. Vadim ZeitlinMar 26, 2020
  2. Johannes SchindelinMar 26, 2020
  3. Re[2]: [PATCH] fetch: allow running as different users in shared repositoriesVadim Zeitlin, Mar 26, 2020
  4. Re[2]: [PATCH] fetch: allow running as different users in shared repositoriesVadim Zeitlin, May 1, 2020
  5. Junio C HamanoMay 4, 2020
  6. Re[2]: [PATCH] fetch: allow running as different users in shared repositoriesVadim Zeitlin, May 4, 2020
  7. Junio C HamanoMay 4, 2020
  8. Re[2]: [PATCH] fetch: allow running as different users in shared repositoriesVadim Zeitlin, May 5, 2020

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.