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

[PATCH 4/5] fast-import: fix buffer overflow in dump_tags

From
Jeff King <peff@peff.net>
Date
Aug 23, 2014, 05:32 UTC
Message-ID
<20140823053237.GD18075@peff.net>
In-Reply-To
<20140823052334.GA17813@peff.net>

When creating a new annotated tag, we sprintf the refname into a static-sized buffer. If we have an absurdly long tagname, like:

  git init repo &&
  cd repo &&
  git commit --allow-empty -m foo &&
  git tag -m message mytag &&
  git fast-export mytag |
  perl -lpe '/^tag/ and s/mytag/"a" x 8192/e' |
  git fast-import <input
we'll overflow the buffer. We can fix it by using a strbuf.
Signed-off-by: Jeff King <peff@peff.net>
---
I'm not sure how easily exploitable this is. The buffer is on the stack,
and we definitely demolish the return address. But we never actually
return from the function, since lock_ref_sha1 will fail in such a case
and die (it cannot succeed because the name is longer than PATH_MAX,
which we check when concatenating it with $GIT_DIR).

Still, there is no limit to the size of buffer you can feed it, so it's entirely possible you can overwrite something else and cause some mischief. So I wouldn't call it trivially exploitable, but I would not bet my servers that it is not (and of course it is easy to trigger if you can convince somebody to run fast-import a stream, so any remote helpers produce a potentially vulnerable situation).

 fast-import.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index f25a4ae..a1479e9 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1734,14 +1734,16 @@ static void dump_tags(void)
 	static const char *msg = "fast-import";
 	struct tag *t;
 	struct ref_lock *lock;
-	char ref_name[PATH_MAX];
+	struct strbuf ref_name = STRBUF_INIT;
 
 	for (t = first_tag; t; t = t->next_tag) {
-		sprintf(ref_name, "tags/%s", t->name);
-		lock = lock_ref_sha1(ref_name, NULL);
+		strbuf_reset(&ref_name);
+		strbuf_addf(&ref_name, "tags/%s", t->name);
+		lock = lock_ref_sha1(ref_name.buf, NULL);
 		if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
-			failure |= error("Unable to update %s", ref_name);
+			failure |= error("Unable to update %s", ref_name.buf);
 	}
+	strbuf_release(&ref_name);
 }
 
 static void dump_marks_helper(FILE *f,
-- 
2.1.0.346.ga0367b9
Previous: Jeff KingNext: Ronnie Sahlberg
Message 7 of 14 in “fix pack-refs pruning of refs/foo”
  1. 0/5 fix pack-refs pruning of refs/fooJeff King, Aug 23, 2014
  2. 1/5 git-prompt: do not look for refs/stash in $GIT_DIRJeff King, Aug 23, 2014
  3. 2/5 pack-refs: prune top-level refs like "refs/foo"Jeff King, Aug 23, 2014
  4. 3/5 fast-import: clean up pack_data pointer in end_packfileJeff King, Aug 23, 2014
  5. Ronnie SahlbergAug 25, 2014
  6. Jeff KingAug 25, 2014
  7. 4/5 fast-import: fix buffer overflow in dump_tagsJeff King, Aug 23, 2014
  8. Ronnie SahlbergAug 25, 2014
  9. 5/5 fast-import: stop using lock_ref_sha1Jeff King, Aug 23, 2014
  10. Ronnie SahlbergAug 25, 2014
  11. Michael HaggertyAug 23, 2014
  12. Jeff KingAug 23, 2014
  13. Ronnie SahlbergAug 25, 2014
  14. Jeff KingAug 25, 2014

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.