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

Re: [PATCH 1/3] prune-packed: fix a possible buffer overflow

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Dec 19, 2013, 16:33 UTC
Message-ID
<52B31FF3.1060102@alum.mit.edu>
In-Reply-To
<20131219000415.GA17420@sigill.intra.peff.net>
On 12/19/2013 01:04 AM, Jeff King wrote:
Show 22 quoted lines
> On Wed, Dec 18, 2013 at 11:44:58PM +0100, Michael Haggerty wrote:
> 
>> [While doing so, I got sidetracked by the question: what happens if a
>> prune process deletes the "objects/XX" directory just the same moment
>> that another process is trying to write an object into that directory?
>> I think the relevant function is sha1_file.c:create_tmpfile().  It looks
>> like there is a nonzero but very small race window that could result in
>> a spurious "unable to create temporary file" error, but even then I
>> don't think there would be any corruption or anything.]
> 
> There's a race there, but I think it's hard to trigger.
> 
> Our strategy with object creation is to call open, recognize ENOENT,
> mkdir, and then try again. If the rmdir happens before our call to open,
> then we're fine. If open happens first, then the rmdir will fail.
> 
> But we don't loop on ENOENT. So if the rmdir happens in the middle,
> after the mkdir but before we call open again, we'd fail, because we
> don't treat ENOENT specially in the second call to open. That is
> unlikely to happen, though, as prune would not be removing a directory
> it did not just enter and clean up an object from (in which case we
> would not have gotten the first ENOENT in the creator). [...]

The way I read it, prune tries to delete the directory whether or not there were any files in it. So the race could be triggered by a single writer that wants to write an object to a not-yet-existent shard directory and a single prune process that encounters the directory between when it is created and when the object file is added.

But that doesn't mean I disagree with your conclusion:
> So it seems unlikely and the worst case is a temporary failure, not a
> corruption. It's probably not worth caring too much about, but we could
> solve it pretty easily by looping on ENOENT on creation.
Regarding references:
> On a similar note, I imagine that a simultaneous "branch foo/bar" and
> "branch -d foo/baz" could race over the creation/deletion of
> "refs/heads/foo", but I didn't look into it.

Deleting a loose reference doesn't cause the directory containing it to be deleted. The directory is only deleted by pack-refs (and then only when a reference in the directory was just packed) or when there is an attempt to create a new reference that conflicts with the directory. So the question is whether the creation of a loose ref file is robust against the disappearance of a directory that it just created.

And the answer is "no". It looks like there are a bunch of places where similar races occur involving references. And probably many others elsewhere in the code. (Any caller of safe_create_leading_directories() is a candidate problem point, and in fact that function itself has an internal race.) I've started fixing some of these but it might take a while.

Michael
-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
Previous: Jeff KingNext: Jeff King
Message 7 of 21 in “Fix two buffer overflows and remove a redundant var”
  1. 0/3 Fix two buffer overflows and remove a redundant varMichael Haggerty, Dec 17, 2013
  2. 1/3 prune-packed: fix a possible buffer overflowMichael Haggerty, Dec 17, 2013
  3. Duy NguyenDec 17, 2013
  4. Junio C HamanoDec 17, 2013
  5. Michael HaggertyDec 18, 2013
  6. Jeff KingDec 19, 2013
  7. Michael HaggertyDec 19, 2013
  8. Jeff KingDec 20, 2013
  9. Duy NguyenDec 19, 2013
  10. 2/3 prune_object_dir(): verify that path fits in the temporary bufferMichael Haggerty, Dec 17, 2013
  11. Junio C HamanoDec 17, 2013
  12. Jeff KingDec 17, 2013
  13. Junio C HamanoDec 18, 2013
  14. Jeff KingDec 18, 2013
  15. Junio C HamanoDec 18, 2013
  16. Jeff KingDec 18, 2013
  17. Junio C HamanoDec 18, 2013
  18. Jeff KingDec 18, 2013
  19. Antoine PelisseDec 17, 2013
  20. 3/3 cmd_repack(): remove redundant local variable "nr_packs"Michael Haggerty, Dec 17, 2013
  21. Stefan BellerDec 17, 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.