Re: Some issues when trying to set up a shallow git mirror server

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Junio C Hamano <gitster@xxxxxxxxx> writes:

> Richard Maw <richard.maw@xxxxxxxxxxxxxxx> writes:
>
>> This is inconvenient for us,
>> as we were explicitly using refspecs which didn't force the fetch,
>> since we were using the "non fast-forward update" errors
>> to detect whether upstream force pushed important refs
>> which could be a sign of tampering.
>>
>> While the client doesn't have enough information
>> the server has those commits.
>> Would it make sense for the server to be able to tell the client
>> "trust me, that commit is a descendant of the previous one"?
>
> It does not in our security model, as you do not blindly trust the
> other side, whether you are a "client" or a "server".

Thinking about it more, I think my answer was flawed.  

A client may ask the server to give a history, and before it accepts
the result, it must do its own consistency check.  A client may send
its history, and before the server accepts it, the server must do
its own consistency check.  This is the general principle around our
consistency model (it is not limited to "security", but it is more
about "correctness" in general).

While that consistency principle must hold everywhere in our system,
it does not mean a client cannot ask a server to do something whose
result it has to trust, at least to some degree, because there is
fundamentally no way to independenty verify the result.

I think what you were hinting falls into that category.  The client
cannot verify that the new tip is a descendant of the old one
without having the full history between these two points, but
transfering that history would defeat the whole point of using a
shallowed history.

So in that sense I do think that such a protocol extension does make
sense.  But it would involve some extra pieces of information that
need to be sent between the client and the server, not just "I'll
trust you".

In the current "git fetch" protocol, the sender gives the receiver a
list of refs, and for each of these refs, the object name it points
at.  Then the receiver asks the sender to give it the objects that
appear in the history leading to a set of objects (aka "want"), and
tells the sender what objects it completely has already (aka
"have").  The idea is that the sender can exclude objects that are
reachable from "have"s when it enumerates the objects that need to
be sent.  When the receiver is shallow, it also tells the sender
that its current history is truncated at such and such commits,
lacking things before them.  After that exchange, the sender just
gives the receiver a packfile that contains the objects requested.
The receiver verifies that the packfile makes sense, e.g. it has all
the "want" objects it asked for, and the objects that they refer to
(recursively) are available, before updating its refs with (some of)
the "want" objects.

In the simplest case, for example, where you might have a single
refs/heads/master that currently points at O and the other side has
N at its refs/heads/master, the sender would say "I have N at
refs/heads/master" and the receiver would say "I want N, and I have
O".  A shallow receiver may also say "I do not have history behind
O" and "I only want a history 1 commit deep".  And the sender would
send objects that is necessary to satisfy the request, e.g. commit N
itself and the trees and blobs in commit N that are not common with
commit O.

Notice that nowhere in this exchange the receiver tells the sender
what it intends to do with the "want" objects?

Because the receiver does not say "I want N and I intend to replace
O I currently have refs/heads/master", there is no way for the
sender to say "trust me, N is a descendant of O".  It simply does
not know if the receiver _cares_ how N and O are related with each
other.

So if you want to do this, a new protocol extension needs to allow
your updated sender (upload-pack) and receiver (fetch-pack) to work
more like this:

 * The sender would advertise "I support that extension", while
   giving the usual "here are my refs and its current values".

 * The receiver would say "I want to use that extension", and to
   each of its "want" (which usually consists of "want" followed by
   an object name and nothing else), it optionally adds names of the
   objects it wants to verify ancestry relationship with.

   E.g. if you have O at the tip of the master branch and P at the
   tip of the maint branch, the sender has N at both of these two
   branches, and if you are updating your master and maint with
   their master and maint, you would say something like "want N O P"
   to tell the sender that you want history leading to N, and you
   want to see if N is a descendant of O and if N is a descendant of
   P.

 * The receiver and the sender then does the usual "have"/"ack"
   exchange, which does not have to change any behaviour with this
   extension.

 * Finally, when the sender sends out the resulting packfile, it
   also has to tell the receiver which of the object pairs the
   receiver asked it to check the ancestry relationship violate the
   fast-forward rule.  In the earlier example of fast-forwarding O
   and P with N, where the receiver asked "want N O P", the receiver
   asked to check object pairs <N, O> and <N, P>.  If P fast-forwards
   to N but O does not, then the sender would tell the receiver the
   fact that "O does not fast forward to N".

With such an extension, your updated receiver can receive the
necessary objects to update your history to "N", but notice that it
would result in non-ff update to update master (that used to be O)
with the new commit N.



--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]