git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: Michael Haggerty <mhagger@alum.mit.edu>
Cc: git@vger.kernel.org
Subject: Re: [PATCH 4/4] create_symref: use existing ref-lock code
Date: Tue, 29 Dec 2015 00:02:30 -0500	[thread overview]
Message-ID: <20151229050230.GA13253@sigill.intra.peff.net> (raw)
In-Reply-To: <568104AF.102@alum.mit.edu>

On Mon, Dec 28, 2015 at 10:45:19AM +0100, Michael Haggerty wrote:

> > +static int create_ref_symlink(struct ref_lock *lock, const char *target)
> [...]
> > +	char *ref_path = get_locked_file_path(lock->lk);
> > +	unlink(ref_path);
> > +	ret = symlink(target, ref_path);
> [...]
> 
> This function is racy. A reader might see no reference at all in the
> moment between the `unlink()` and the `symlink()`. Moreover, if this
> process is killed at that moment, the symbolic ref would be gone forever.
> 
> I think that the semantics of `rename()` would allow this race to be
> fixed, though, since `symlink()` doesn't have the analogue of
> `O_CREAT|O_EXCL`, one would need a lockfile *and* a second temporary
> filename under which the new symlink is originally created.
> 
> However, this race has always been here, and symlink-based symrefs are
> obsolete, so it's probably not worth fixing.

Yeah. In the commit message I wrote:

> >  - the legacy prefer_symlink_refs path did not do any
> >    locking at all. Admittedly, it is not atomic from a
> >    reader's perspective (and it cannot be; it has to unlink
> >    and then symlink, creating a race), but at least it
> >    cannot conflict with other writers now.

but I think you are right that we could do tricks with rename() on the
symlink. That is in POSIX, though I wouldn't be surprised if it
misbehaves on some obscure systems. Given that using symlinks is only
triggered by an undocumented (!) option that presumably very few people
use, I'm inclined to leave it as-is.

I was actually tempted to rip it out, as the option is mostly a hack
from 2006:

  http://article.gmane.org/gmane.comp.version-control.git/19402

It was done to let people bisect old kernel trees whose build system
_depends_ on .git/HEAD being a symlink. My thought is:

  - people are a lot less likely to bisect back that far anymore

  - ...and if they do, their build system will be totally broken by the
    new ref-backend stuff

  - ...and the right solution is not to put a hack in git, but for the
    bisecting user to "fix up" the tree before testing (by munging the
    symlink themselves, or applying a patch to the build system to use
    `git rev-parse`). This matches what people have to do for every
    other type of weird "the old version doesn't quite build"
    incompatibility that has nothing to do with git.

But that should probably come as a separate patch (it affects this only
in that it makes this patch simpler to do that cleanup first :) ).

> > +	if (adjust_shared_perm(lock->lk->tempfile.filename.buf))
> > +		return error("unable to fix permissions on %s: %s",
> > +			     lock->lk->tempfile.filename.buf, strerror(errno));
> 
> You can skip this step. lock_file() already calls adjust_shared_perm().

Thanks, fixed.

> > +	/* no error check; commit_ref will check ferror */
> > +	fprintf(lock->lk->tempfile.fp, "ref: %s\n", target);
> > +	if (commit_ref(lock) < 0)
> > +		return error("unable to write symref for %s: %s", ref,
> > +			     strerror(errno));
> > +	update_symref_reflog(lock, ref, target, logmsg);
> 
> Here is another problem that didn't originate with your changes:
> 
> The reflog should be written while holding the reference lock, to
> prevent two processes' trying to write new entries at the same time.
> 
> I think the problem would be solved if you move the call to
> update_symref_reflog() above the call to commit_ref().
> 
> Granted, this could case a reflog entry to be written for a reference
> update whose commit fails, but that's also a risk for non-symbolic
> references. Fixing this residual problem would require the ability to
> roll back reflog changes.

Thanks, I agree with your reasoning (and especially that we should err
on the same side that normal ref-writing does). I'll do it in a
follow-on patch, though, to make it more clear what is going on.

-Peff

  reply	other threads:[~2015-12-29  5:02 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-20  7:26 [PATCH 0/4] improve symbolic-ref robustness Jeff King
2015-12-20  7:27 ` [PATCH 1/4] symbolic-ref: propagate error code from create_symref() Jeff King
2015-12-20  7:27 ` [PATCH 2/4] t1401: test reflog creation for git-symbolic-ref Jeff King
2015-12-20  7:29 ` [PATCH 3/4] create_symref: modernize variable names Jeff King
2015-12-28  8:20   ` Michael Haggerty
2015-12-29  5:02     ` Jeff King
2015-12-20  7:34 ` [PATCH 4/4] create_symref: use existing ref-lock code Jeff King
2015-12-21 20:50   ` Junio C Hamano
2015-12-22  0:58     ` Jeff King
2015-12-28  9:45   ` Michael Haggerty
2015-12-29  5:02     ` Jeff King [this message]
2015-12-29  5:41       ` Jeff King
2015-12-29  5:55 ` [PATCH v2 0/3] improve symbolic-ref robustness Jeff King
2015-12-29  5:56   ` [PATCH 1/3] create_symref: modernize variable names Jeff King
2015-12-29  5:57   ` [PATCH 2/3] create_symref: use existing ref-lock code Jeff King
2015-12-29  5:57   ` [PATCH 3/3] create_symref: write reflog while holding lock Jeff King
2015-12-29  6:00   ` [RFC/PATCH 4/3] create_symref: drop support for writing symbolic links Jeff King
2015-12-29  6:03     ` Jeff King
2015-12-29 18:32     ` Junio C Hamano
2015-12-30  6:53       ` Jeff King
2015-12-30  6:56         ` Jeff King
2015-12-29  8:25   ` [PATCH v2 0/3] improve symbolic-ref robustness Michael Haggerty
2015-12-29 18:35     ` Junio C Hamano
2015-12-29 21:24   ` Junio C Hamano
2015-12-30  6:57     ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151229050230.GA13253@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=mhagger@alum.mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).