path: root/transport.c
diff options
authorDenton Liu <>2020-05-19 10:54:00 (GMT)
committerJunio C Hamano <>2020-05-24 23:26:00 (GMT)
commitb0df0c16ead4c5512d506dcbbdf31194d992803c (patch)
treec2a5f0b8bfb8fd410c5b3b1217202d8f91e3df39 /transport.c
parent0181b600a6deb66a346dbcbe8300cf9e2467ebbb (diff)
stateless-connect: send response end packet
Currently, remote-curl acts as a proxy and blindly forwards packets between an HTTP server and fetch-pack. In the case of a stateless RPC connection where the connection is terminated before the transaction is complete, remote-curl will blindly forward the packets before waiting on more input from fetch-pack. Meanwhile, fetch-pack will read the transaction and continue reading, expecting more input to continue the transaction. This results in a deadlock between the two processes. This can be seen in the following command which does not terminate: $ git -c protocol.version=2 clone --shallow-since=20151012 Cloning into 'git'... whereas the v1 version does terminate as expected: $ git -c protocol.version=1 clone --shallow-since=20151012 Cloning into 'git'... fatal: the remote end hung up unexpectedly Instead of blindly forwarding packets, make remote-curl insert a response end packet after proxying the responses from the remote server when using stateless_connect(). On the RPC client side, ensure that each response ends as described. A separate control packet is chosen because we need to be able to differentiate between what the remote server sends and remote-curl's control packets. By ensuring in the remote-curl code that a server cannot send response end packets, we prevent a malicious server from being able to perform a denial of service attack in which they spoof a response end packet and cause the described deadlock to happen. Reported-by: Force Charlie <> Helped-by: Jeff King <> Signed-off-by: Denton Liu <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'transport.c')
1 files changed, 2 insertions, 1 deletions
diff --git a/transport.c b/transport.c
index 431a93c..7d50c50 100644
--- a/transport.c
+++ b/transport.c
@@ -297,7 +297,8 @@ static struct ref *handshake(struct transport *transport, int for_push,
if (must_list_refs)
get_remote_refs(data->fd[1], &reader, &refs, for_push,
- transport->server_options);
+ transport->server_options,
+ transport->stateless_rpc);
case protocol_v1:
case protocol_v0: