January 9, 2015

Git Out of the Vulnerability AND Out of the Fire

Git at Scale

git out of the fire

I suggested updating your Git clients in a recent blog post because of a new Git release that addressed a critical vulnerability (CVE-2014-9390 for those interested). Git users at Perforce have subsequently identified some unhappy side effects, and our internal brain trust has worked up a simple approach for dealing with them. The purpose of this blog post is to explain the problem and highlight the fix for the good of the larger Git community.

The original Git release announcement suggested enabling a configuration parameter named “fsckObjects”, because it would reject any attempt to push a repo that could exploit the potential vulnerability. The resulting problem is that this can cause older repos to fail when pushing, cloning, etc. due to warnings about “zero-padded file modes”.

For those to whom Git-speak isn’t a second language, this particular warning dates all the way back to a fix introduced in 2005 to be stricter about tree objects, fixing zero-padding of the mode bits. The zero-padding problem caused otherwise identical trees to have different hash values, and since the SHA1 hash value is essentially the key for the underlying object storage, the result is multiple copies of the same stuff. Not good.

History/plumbing lesson aside, the still-simpler version of the story is that it was an important bug fix, but of course not everybody immediately ran out and cleaned up their repos. As such, older repos that still suffer from the problem (e.g., Flask) now fail during common operations once fsckObjects is newly enabled. The simplest workaround is clever but not obvious. Here’s an example:

mkdir myFixedRepo
cd myFixedRepo
git init
cd ../myBadRepo
git fast-export --all | (cd ../myFixedRepo; git fast-import)1

The “trick” is that when you find a repo that has the padding issue—and a simple “git fsck” command will show this—you create a new repo to contain the fixed version and rely on the Git fast export/import commands to bring the data across. The only down side is that this will end up creating new SHA1 hash values, but it remains the price of fixing the issue. If you’ve already pushed somewhere, you’ll probably want to push to another repo to avoid the perils of a forced push, but that’s a story for another day; if you can’t live with the changed hash values, then disabling fsckObjects is probably the better choice.

1 Windows users try this command-line instead: git fast-export --all | (cd ../myFixedRepo & git fast-import)