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

[PATCH 3/3] remote-curl: sanity check ref advertisement from server

From
Jeff King <peff@peff.net>
Date
Feb 16, 2013, 06:49 UTC
Message-ID
<20130216064929.GC22626@sigill.intra.peff.net>
In-Reply-To
<20130216064455.GA27063@sigill.intra.peff.net>

If the smart HTTP response from the server is truncated for any reason, we will get an incomplete ref advertisement. If we then feed this incomplete list to "fetch-pack", one of a few things may happen:

  1. If the truncation is in a packet header, fetch-pack
     will notice the bogus line and complain.
  2. If the truncation is inside a packet, fetch-pack will
     keep waiting for us to send the rest of the packet,
     which we never will.
  3. If the truncation is at a packet boundary, fetch-pack
     will keep waiting for us to send the next packet, which
     we never will.

As a result, fetch-pack hangs, waiting for input. However, remote-curl believes it has sent all of the advertisement, and therefore waits for fetch-pack to speak. The two processes end up in a deadlock.

This fortunately doesn't happen in the normal fetching workflow, because git-fetch first uses the "list" command, which feeds the refs to get_remote_heads, which does notice the error. However, you can trigger it by sending a direct "fetch" to the remote-curl helper.

We can make this more robust by verifying that the packet stream we got from the server does indeed parse correctly and ends with a flush packet, which means that what fetch-pack receives will at least be syntactically correct.

The normal non-stateless-rpc case does not have to deal with this problem; it detects a truncation by getting EOF on the file descriptor before it has read all data. So it is tempting to think that we can solve this by closing the descriptor after relaying the server's advertisement. Unfortunately, in the stateless rpc case, we need to keep the descriptor to fetch-pack open in order to pass more data to it.

We could solve that by using two descriptors, but our run-command interface does not support that (and modifying it to create more pipes would make life hard for the Windows port of git).

Signed-off-by: Jeff King <peff@peff.net>
---
 remote-curl.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
diff --git a/remote-curl.c b/remote-curl.c
index 73134f5..c7647c7 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -101,6 +101,15 @@ static int read_packets_until_flush(char **buf, size_t *len)
 	}
 }
 
+static int verify_ref_advertisement(char *buf, size_t len)
+{
+	/*
+	 * Our function parameters are copies, so we do not
+	 * have to care that read_packets will increment our pointers.
+	 */
+	return read_packets_until_flush(&buf, &len);
+}
+
 static struct discovery* discover_refs(const char *service)
 {
 	struct strbuf exp = STRBUF_INIT;
@@ -174,6 +183,9 @@ static struct discovery* discover_refs(const char *service)
 			die("smart-http metadata lines are invalid at %s",
 			    refs_url);
 
+		if (verify_ref_advertisement(last->buf, last->len) < 0)
+			die("ref advertisement is invalid at %s", refs_url);
+
 		last->proto_git = 1;
 	}
 
-- 
1.8.1.2.11.g1a2f572
Previous: Jeff KingNext: Jonathan Nieder
Message 9 of 50 in “make smart-http more robust against bogus server input”
  1. 0/3 make smart-http more robust against bogus server inputJeff King, Feb 16, 2013
  2. 1/3 pkt-line: teach packet_get_line a no-op modeJeff King, Feb 16, 2013
  3. Jonathan NiederFeb 17, 2013
  4. 2/3 remote-curl: verify smart-http metadata linesJeff King, Feb 16, 2013
  5. Jonathan NiederFeb 17, 2013
  6. Jeff KingFeb 17, 2013
  7. Jonathan NiederFeb 18, 2013
  8. Jeff KingFeb 18, 2013
  9. 3/3 remote-curl: sanity check ref advertisement from serverJeff King, Feb 16, 2013
  10. Jonathan NiederFeb 17, 2013
  11. Jeff KingFeb 17, 2013
  12. Jonathan NiederFeb 18, 2013
  13. 0/10 pkt-line and remote-curl cleanups serverJeff King, Feb 18, 2013
  14. 01/10 pkt-line: move a misplaced commentJeff King, Feb 18, 2013
  15. 02/10 pkt-line: drop safe_write functionJeff King, Feb 18, 2013
  16. Jonathan NiederFeb 18, 2013
  17. Jeff KingFeb 18, 2013
  18. 03/10 pkt-line: clean up "gentle" reading functionJeff King, Feb 18, 2013
  19. Jonathan NiederFeb 18, 2013
  20. Jeff KingFeb 18, 2013
  21. 04/10 pkt-line: change error message for oversized packetJeff King, Feb 18, 2013
  22. Junio C HamanoFeb 18, 2013
  23. Jeff KingFeb 18, 2013
  24. Junio C HamanoFeb 18, 2013
  25. Jeff KingFeb 18, 2013
  26. Jeff KingFeb 20, 2013
  27. Junio C HamanoFeb 20, 2013
  28. Jonathan NiederFeb 18, 2013
  29. Jeff KingFeb 18, 2013
  30. 05/10 pkt-line: rename s/packet_read_line/packet_read/Jeff King, Feb 18, 2013
  31. Jonathan NiederFeb 18, 2013
  32. Jeff KingFeb 18, 2013
  33. Jonathan NiederFeb 18, 2013
  34. 06/10 pkt-line: share buffer/descriptor reading implementationJeff King, Feb 18, 2013
  35. Jonathan NiederFeb 18, 2013
  36. Jeff KingFeb 18, 2013
  37. Jonathan NiederFeb 18, 2013
  38. 07/10 teach get_remote_heads to read from a memory bufferJeff King, Feb 18, 2013
  39. 08/10 remote-curl: pass buffer straight to get_remote_headsJeff King, Feb 18, 2013
  40. Jonathan NiederFeb 18, 2013
  41. Junio C HamanoFeb 18, 2013
  42. Jeff KingFeb 18, 2013
  43. Junio C HamanoFeb 18, 2013
  44. Jeff KingFeb 18, 2013
  45. Shawn PearceFeb 20, 2013
  46. 09/10 remote-curl: move ref-parsing code up in fileJeff King, Feb 18, 2013
  47. 10/10 remote-curl: always parse incoming refsJeff King, Feb 18, 2013
  48. Jonathan NiederFeb 18, 2013
  49. Shawn PearceFeb 20, 2013
  50. Shawn PearceFeb 20, 2013

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.