skip checkRepoConfigInaccessible when git directory specified explicitly

Fix a reversion that prevented git-annex from working in a repository when
--git-dir or GIT_DIR is specified to relocate the git directory to
somewhere else. (Introduced in version 10.20220525)

checkRepoConfigInaccessible could still run git config --list, just passing
--git-dir. It seems not necessary, because I know that passing --git-dir
bypasses git's check for repo ownership. I suppose it might be that git
eventually changes to check something about the ownership of the working
tree, so passing --git-dir without --work-tree would still be worth doing.
But for now this is the simple fix.

Sponsored-by: Nicholas Golder-Manning on Patreon
This commit is contained in:
Joey Hess 2022-09-20 14:52:43 -04:00
parent d1467a9b8e
commit 8d26fdd670
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
6 changed files with 61 additions and 17 deletions

View file

@ -23,6 +23,10 @@ git-annex (10.20220823) UNRELEASED; urgency=medium
that it had changed, due to only accepting the inode+mtime of one file that it had changed, due to only accepting the inode+mtime of one file
(that was since modified or deleted) and not accepting the inode+mtime (that was since modified or deleted) and not accepting the inode+mtime
of other duplicate files. of other duplicate files.
* Fix a reversion that prevented git-annex from working in a
repository when --git-dir or GIT_DIR is specified to relocate the git
directory to somewhere else.
(Introduced in version 10.20220525)
-- Joey Hess <id@joeyh.name> Mon, 29 Aug 2022 15:03:04 -0400 -- Joey Hess <id@joeyh.name> Mon, 29 Aug 2022 15:03:04 -0400

View file

@ -282,16 +282,20 @@ unset ck@(ConfigKey k) r = ifM (Git.Command.runBool ps r)
- repo. - repo.
-} -}
checkRepoConfigInaccessible :: Repo -> IO Bool checkRepoConfigInaccessible :: Repo -> IO Bool
checkRepoConfigInaccessible r = do checkRepoConfigInaccessible r
-- Cannot use gitCommandLine here because specifying --git-dir -- When --git-dir or GIT_DIR is used to specify the git
-- will bypass the git security check. -- directory, git does not check for CVE-2022-24765.
let p = (proc "git" ["config", "--local", "--list"]) | gitDirSpecifiedExplicitly r = return False
{ cwd = Just (fromRawFilePath (repoPath r)) | otherwise = do
, env = gitEnv r -- Cannot use gitCommandLine here because specifying --git-dir
} -- will bypass the git security check.
(out, ok) <- processTranscript' p Nothing let p = (proc "git" ["config", "--local", "--list"])
if not ok { cwd = Just (fromRawFilePath (repoPath r))
then do , env = gitEnv r
debug (DebugSource "Git.Config") ("config output: " ++ out) }
return True (out, ok) <- processTranscript' p Nothing
else return False if not ok
then do
debug (DebugSource "Git.Config") ("config output: " ++ out)
return True
else return False

View file

@ -277,5 +277,6 @@ newFrom l = Repo
, gitEnv = Nothing , gitEnv = Nothing
, gitEnvOverridesGitDir = False , gitEnvOverridesGitDir = False
, gitGlobalOpts = [] , gitGlobalOpts = []
, gitDirSpecifiedExplicitly = False
} }

View file

@ -1,6 +1,6 @@
{- The current git repository. {- The current git repository.
- -
- Copyright 2012-2020 Joey Hess <id@joeyh.name> - Copyright 2012-2022 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -80,9 +80,10 @@ get = do
, worktree = Just curr , worktree = Just curr
} }
r <- Git.Config.read $ newFrom loc r <- Git.Config.read $ newFrom loc
return $ if Git.Config.isBare r let r' = r { gitDirSpecifiedExplicitly = True }
then r { location = (location r) { worktree = Nothing } } return $ if Git.Config.isBare r'
else r then r' { location = (location r) { worktree = Nothing } }
else r'
configure Nothing Nothing = giveup "Not in a git repository." configure Nothing Nothing = giveup "Not in a git repository."
addworktree w r = changelocation r $ Local addworktree w r = changelocation r $ Local

View file

@ -51,6 +51,8 @@ data Repo = Repo
, gitEnvOverridesGitDir :: Bool , gitEnvOverridesGitDir :: Bool
-- global options to pass to git when running git commands -- global options to pass to git when running git commands
, gitGlobalOpts :: [CommandParam] , gitGlobalOpts :: [CommandParam]
-- True only when --git-dir or GIT_DIR was used
, gitDirSpecifiedExplicitly :: Bool
} deriving (Show, Eq, Ord) } deriving (Show, Eq, Ord)
newtype ConfigKey = ConfigKey S.ByteString newtype ConfigKey = ConfigKey S.ByteString

View file

@ -18,3 +18,35 @@ Simple test case:
failed failed
And --debug shows:
[2022-09-20 14:17:56.238686901] (Utility.Process) process [1284622] read: git ["config","--local","--list"]
[2022-09-20 14:17:56.240836887] (Utility.Process) process [1284622] done ExitFailure 128
[2022-09-20 14:17:56.24107763] (Git.Config) config output: fatal: --local can only be used inside a git repository
So passing --git-dir to that command will make it succeeed. The problem
though is that passing --git-dir to that command also bypasses git's
fix for CVE-2022-24765. The command would even succeed if the directory
were owned by someone else then.
joey@darkstar:/tmp/foo>sudo chown -R root.root .
[sudo] password for joey:
joey@darkstar:/tmp/foo>git --git-dir=`pwd`/.dotfiles config --local --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.worktree=/tmp/foo
joey@darkstar:/tmp/foo>git config --local --list
fatal: --local can only be used inside a git repository
But, if the user runs git-annex with an explicit --git-dir,
it's actually ok for git-annex to bypass the CVE-2022-24765 check.
Because --git-dir actually bypasses that check.
So, the fix for this seems like it will involve it remembering
when the git repo was originally specified using --git-dir (or `GIT_DIR`),
and if so, guardSafeToUseRepo can skip the check, or pass --git-dir to
`git config --local --list`.
> [[fixed|done]] --[[Joey]]