Revert "revert recent bug fix temporarily for release"
authorJoey Hess <joeyh@joeyh.name>
Tue, 14 Feb 2023 18:11:23 +0000 (14:11 -0400)
committerJoey Hess <joeyh@joeyh.name>
Tue, 14 Feb 2023 18:11:23 +0000 (14:11 -0400)
This reverts commit 16f1e2466595da27a56c1a67846ba68a9692b365.

Assistant/MakeRepo.hs
CHANGELOG
Database/Keys.hs
Git/Config.hs
Git/Construct.hs
Git/CurrentRepo.hs
Remote/Git.hs
doc/bugs/bare_remote_safe_directory.mdwn

index bad4951b1df29dd72f60eb709ac5a3f82b04094c..06a0a659d01da5042344a5f2d1760e1e3b761263 100644 (file)
@@ -57,7 +57,7 @@ initRepo True primary_assistant_repo dir desc mgroup = inDir dir $ do
        initRepo' desc mgroup
        {- Initialize the master branch, so things that expect
         - to have it will work, before any files are added. -}
-       unlessM (Git.Config.isBare <$> gitRepo) $ do
+       unlessM (fromMaybe False . Git.Config.isBare <$> gitRepo) $ do
                cmode <- annexCommitMode <$> Annex.getGitConfig
                void $ inRepo $ Git.Branch.commitCommand cmode
                        (Git.Branch.CommitQuiet True)
index 926f6bd79a0b3703d8c9180a35970eaa127d533f..477273d9eb570b4b7033581c55c6a2bd2389a4c4 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,11 @@
+git-annex (10.20230215) UNRELEASED; urgency=medium
+
+  * Fix more breakage caused by git's fix for CVE-2022-24765, this time
+    involving a remote that is a local bare repository not owned by the
+    current user.
+
+ -- Joey Hess <id@joeyh.name>  Tue, 14 Feb 2023 14:11:11 -0400
+
 git-annex (10.20230214) upstream; urgency=medium
 
   * sync: Fix a bug that caused files to be removed from an 
index 9e1043edaef94181a11ac0114c786ae14ed488d1..9f78578c12511adec9b9b5ea68e3ffca4fdf58f8 100644 (file)
@@ -52,7 +52,7 @@ import Git.Sha
 import Git.CatFile
 import Git.Branch (writeTreeQuiet, update')
 import qualified Git.Ref
-import qualified Git.Config
+import Config
 import Config.Smudge
 import qualified Utility.RawFilePath as R
 
@@ -176,7 +176,7 @@ getAssociatedFiles k = emptyWhenBare $ runReaderIO AssociatedTable $
  - in a bare repository, but it might happen if a non-bare repo got
  - converted to bare. -}
 emptyWhenBare :: Annex [a] -> Annex [a]
-emptyWhenBare a = ifM (Git.Config.isBare <$> gitRepo)
+emptyWhenBare a = ifM isBareRepo
        ( return []
        , a
        )
@@ -261,7 +261,7 @@ isInodeKnown i s = or <$> runReaderIO ContentTable
  - is an associated file.
  -}
 reconcileStaged :: Bool -> H.DbQueue -> Annex DbTablesChanged
-reconcileStaged dbisnew qh = ifM (Git.Config.isBare <$> gitRepo)
+reconcileStaged dbisnew qh = ifM isBareRepo
        ( return mempty
        , do
                gitindex <- inRepo currentIndexFile
index e788a2da5509f9bcf004ed8f3d41aceb07a34d52..7e12a568e0bea6438ea75c35892b957fb0474935 100644 (file)
@@ -133,14 +133,28 @@ store' k v repo = repo
  - based on the core.bare and core.worktree settings.
  -}
 updateLocation :: Repo -> IO Repo
-updateLocation r@(Repo { location = LocalUnknown d })
-       | isBare r = ifM (doesDirectoryExist (fromRawFilePath dotgit))
-                       ( updateLocation' r $ Local dotgit Nothing
-                       , updateLocation' r $ Local d Nothing
-                       )
-       | otherwise = updateLocation' r $ Local dotgit (Just d)
+updateLocation r@(Repo { location = LocalUnknown d }) = case isBare r of
+       Just True -> ifM (doesDirectoryExist (fromRawFilePath dotgit))
+               ( updateLocation' r $ Local dotgit Nothing
+               , updateLocation' r $ Local d Nothing
+               )
+       Just False -> mknonbare
+       {- core.bare not in config, probably because safe.directory
+        - did not allow reading the config -}
+       Nothing -> ifM (Git.Construct.isBareRepo (fromRawFilePath d))
+               ( mkbare
+               , mknonbare
+               )
   where
        dotgit = d P.</> ".git"
+       -- git treats eg ~/foo as a bare git repository located in
+       -- ~/foo/.git if ~/foo/.git/config has core.bare=true
+       mkbare = ifM (doesDirectoryExist (fromRawFilePath dotgit))
+               ( updateLocation' r $ Local dotgit Nothing
+               , updateLocation' r $ Local d Nothing
+               )
+       mknonbare = updateLocation' r $ Local dotgit (Just d)
+
 updateLocation r@(Repo { location = l@(Local {}) }) = updateLocation' r l
 updateLocation r = return r
 
@@ -212,8 +226,9 @@ boolConfig' :: Bool -> S.ByteString
 boolConfig' True = "true"
 boolConfig' False = "false"
 
-isBare :: Repo -> Bool
-isBare r = fromMaybe False $ isTrueFalse' =<< getMaybe coreBare r
+{- Note that repoIsLocalBare is often better to use than this. -}
+isBare :: Repo -> Maybe Bool
+isBare r = isTrueFalse' =<< getMaybe coreBare r
 
 coreBare :: ConfigKey
 coreBare = "core.bare"
index 89b1e1fafed1ecddacde1edf7a3a7b6358805d81..f82a3e91a14160446db9e282fc7180e48b0f8f83 100644 (file)
@@ -1,6 +1,6 @@
 {- Construction of Git Repo objects
  -
- - Copyright 2010-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2023 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -23,6 +23,7 @@ module Git.Construct (
        checkForRepo,
        newFrom,
        adjustGitDirFile,
+       isBareRepo,
 ) where
 
 #ifndef mingw32_HOST_OS
@@ -216,7 +217,7 @@ checkForRepo :: FilePath -> IO (Maybe RepoLocation)
 checkForRepo dir = 
        check isRepo $
                check (checkGitDirFile (toRawFilePath dir)) $
-                       check isBareRepo $
+                       check (checkdir (isBareRepo dir)) $
                                return Nothing
   where
        check test cont = maybe cont (return . Just) =<< test
@@ -225,16 +226,17 @@ checkForRepo dir =
                , return Nothing
                )
        isRepo = checkdir $ 
-               gitSignature (".git" </> "config")
+               doesFileExist (dir </> ".git" </> "config")
                        <||>
                -- A git-worktree lacks .git/config, but has .git/gitdir.
                -- (Normally the .git is a file, not a symlink, but it can
                -- be converted to a symlink and git will still work;
                -- this handles that case.)
-               gitSignature (".git" </> "gitdir")
-       isBareRepo = checkdir $ gitSignature "config"
-               <&&> doesDirectoryExist (dir </> "objects")
-       gitSignature file = doesFileExist $ dir </> file
+               doesFileExist (dir </>  ".git" </> "gitdir")
+
+isBareRepo :: FilePath -> IO Bool
+isBareRepo dir = doesFileExist (dir </> "config")
+       <&&> doesDirectoryExist (dir </> "objects")
 
 -- Check for a .git file.
 checkGitDirFile :: RawFilePath -> IO (Maybe RepoLocation)
index 3b607d7babc616c543d9a8f8b60b0d59ce1a9e21..54e05f4ac58d1edb23364a0627e7161c01599c73 100644 (file)
@@ -81,7 +81,7 @@ get = do
                        }
                r <- Git.Config.read $ (newFrom loc)
                        { gitDirSpecifiedExplicitly = True }
-               return $ if Git.Config.isBare r
+               return $ if fromMaybe False (Git.Config.isBare r)
                        then r { location = (location r) { worktree = Nothing } }
                        else r
        configure Nothing Nothing = giveup "Not in a git repository."
index 34fb902c56c33597481b83ebcc5757bc98add8f5..d42b0fa39611c7fc41e593aaa1829ce2aa27d386 100644 (file)
@@ -304,7 +304,7 @@ tryGitConfigRead autoinit r hasuuid
                        Right r' -> do
                                -- Cache when http remote is not bare for
                                -- optimisation.
-                               unless (Git.Config.isBare r') $
+                               unless (fromMaybe False $ Git.Config.isBare r') $
                                        setremote setRemoteBare False
                                return r'
                        Left err -> do
index e21eca86a6ad5a7ce443d2d7fd82e728dc1924f5..b05c490ec4c6561843cf2863c09114b90ff64913 100644 (file)
@@ -12,15 +12,4 @@ This is specific to bare git remotes, for non-bare it
 detects and warns that safe.directory is needed to use the
 remote. --[[Joey]]
 
-> What's causing this is that Git.Config.read is called
-> on the repo, but git refuses to list the repo's config,
-> so updateLocation does not see that the repo is bare
-> when it checks isBare. And so it proceeds to set gitdir
-> to the default non-bare "dir/.git" value.
-> 
-> One way to deal with this would be to make isBare a tristate,
-> since core.bare is not in the listed config at all.
-> 
-> Or, make Git.Construct.fromPath detect when a repo is bare
-> w/o parsing config, and indicate that in the Repo it
-> generates.
+> [[fixed|done]] --[[Joey]]