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

Re: Potential problem in git-add may corrupt the index file

From
GHGang Hu <ganghu@cs.columbia.edu>
Date
Apr 29, 2012, 22:39 UTC
Message-ID
<CAEJt7hbKFKN8J5jjX9Z_Apnco+YiN0kYn=wrHTYjE9P9M=jjaw@mail.gmail.com>
In-Reply-To
<xmqq4ns9j3rf.fsf@junio.mtv.corp.google.com>
Hi Junio,

Thanks for the fast reply! We've also discovered other similar programs in git, enclosed below so you may want to fix them in one patch.

Here is one example in refs.c:
1710:  lockpath = mkpath("%s.lock", git_HEAD);
        fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
....
      written = write_in_full(fd, ref, len);
// We may add
// fsync_or_die(fd, ...);
// here
      if (close(fd) != 0 || written != len) {
              error("Unable to write to %s", lockpath);
              goto error_unlink_return;
      }
      if (rename(lockpath, git_HEAD) < 0) {
...
So there is a problem here, and the head file may be corrupted.
In server-info.c, there is a similar problem:
216:   namelen = sprintf(infofile, "%s/info/packs", get_object_directory());
         strcpy(name, infofile);
         strcpy(name + namelen, "+");
         init_pack_info(infofile, force);
         safe_create_leading_directories(name);
         fp = fopen(name, "w");
         if (!fp)
                 return error("cannot open %s", name);
         write_pack_info_file(fp);
// We may add
// fsync_or_die(fileno(fp), ...);
// here
         fclose(fp);
         adjust_shared_perm(name);
         rename(name, infofile);
Here, the packs file in the objects/info directory may be corrupted.
In the same file, the info/refs file may also be corrupted:
28:  char *path0 = git_pathdup("info/refs");
      int len = strlen(path0);
      char *path1 = xmalloc(len + 2);
      strcpy(path1, path0);
      strcpy(path1 + len, "+");
      safe_create_leading_directories(path0);
      info_ref_fp = fopen(path1, "w");
      if (!info_ref_fp)
              return error("unable to update %s", path1);
      for_each_ref(add_info_ref, NULL);
// We may add
// fsync_or_die(fileno(info_ref_fp), ...);
// here
      fclose(info_ref_fp);
      adjust_shared_perm(path1);
      rename(path1, path0);
On Mon, Apr 23, 2012 at 9:51 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 13 quoted lines
> Gang Hu <ganghu@cs.columbia.edu> writes:
>
>> If a crash happens after the rename(), the data may have not been
>> completely flushed into the index file, so the user may face an empty
>> or corrupted index file.
>
> Yeah, probably we should add fsync_or_die() at the end of write_index()
> in read-cache.c, possibly protect it with fsync_object_files just like
> we do in close_sha1_file() in sha1_file.c for loose object files.
>
> I think the real fix would be to update the write_index() codepath to
> use the csum-file API, though.  Then sha1close() will give us the fsync
> behaviour for free.
-- 
Cheers,
Gang
Previous: Junio C Hamano
Message 3 of 3 in “Potential problem in git-add may corrupt the index file”
  1. Gang HuApr 23, 2012
  2. Junio C HamanoApr 24, 2012
  3. Gang HuApr 29, 2012

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.