From: Joey Hess Date: Tue, 27 Jul 2021 16:29:10 +0000 (-0400) Subject: fix potential race in updating inode cache X-Git-Tag: archive/raspbian/10.20250416-2+rpi1~1^2~91^2~30 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=e4b2a067e0ac96fcdebc691086dd2e5df28881a8;p=git-annex.git fix potential race in updating inode cache In Annex.Content, the object file was statted after pointer files were populated. But if annex.thin is set, once the pointer files are populated, the object file can potentially be modified via the hard link. So, it was possible, though seemingly very unlikely, for the inode of the modified object file to be cached. Command.Fix and Command.Fsck had similar problems, statting the work tree files after they were in place. Changed them to stat the temp file that gets moved into place. This does rely on .git/annex being on the same filesystem. If it's not, the cached inode will not be the same as the one that the temp file gets moved to. Result will be that git-annex will later need to do an expensive verification of the content of the worktree files. Note that the cross-filesystem move of the temp file already is a larger amount of extra work, so this seems acceptable. Sponsored-by: Luke Shumaker on Patreon --- diff --git a/Annex/Content.hs b/Annex/Content.hs index 86a3a97998..50522a2098 100644 --- a/Annex/Content.hs +++ b/Annex/Content.hs @@ -346,8 +346,11 @@ moveAnnex key af src = ifM (checkSecureHashes' key) fs <- map (`fromTopFilePath` g) <$> Database.Keys.getAssociatedFiles key unless (null fs) $ do + destic <- withTSDelta $ + liftIO . genInodeCache dest ics <- mapM (populatePointerFile (Restage True) key dest) fs - Database.Keys.storeInodeCaches' key [dest] (catMaybes ics) + Database.Keys.addInodeCaches key + (catMaybes (destic:ics)) ) alreadyhave = liftIO $ R.removeLink src diff --git a/Command/Fix.hs b/Command/Fix.hs index 6a84652cea..49e5ca9786 100644 --- a/Command/Fix.hs +++ b/Command/Fix.hs @@ -77,8 +77,8 @@ breakHardLink file key obj = do unlessM (checkedCopyFile key obj tmp' mode) $ error "unable to break hard link" thawContent tmp' + Database.Keys.storeInodeCaches key [tmp'] modifyContent obj $ freezeContent obj - Database.Keys.storeInodeCaches key [file] next $ return True makeHardLink :: RawFilePath -> Key -> CommandPerform diff --git a/Command/Fsck.hs b/Command/Fsck.hs index 9a2b2407b5..7338a362e2 100644 --- a/Command/Fsck.hs +++ b/Command/Fsck.hs @@ -363,7 +363,7 @@ verifyWorkTree key file = do void $ checkedCopyFile key obj tmp' mode thawContent tmp' ) - Database.Keys.storeInodeCaches key [file] + Database.Keys.storeInodeCaches key [tmp'] _ -> return () return True diff --git a/Database/Keys.hs b/Database/Keys.hs index f79716c4e5..83a3e7a49e 100644 --- a/Database/Keys.hs +++ b/Database/Keys.hs @@ -18,7 +18,6 @@ module Database.Keys ( getAssociatedKey, removeAssociatedFile, storeInodeCaches, - storeInodeCaches', addInodeCaches, getInodeCaches, removeInodeCaches, @@ -175,11 +174,8 @@ removeAssociatedFile k = runWriterIO . SQL.removeAssociatedFile k {- Stats the files, and stores their InodeCaches. -} storeInodeCaches :: Key -> [RawFilePath] -> Annex () -storeInodeCaches k fs = storeInodeCaches' k fs [] - -storeInodeCaches' :: Key -> [RawFilePath] -> [InodeCache] -> Annex () -storeInodeCaches' k fs ics = withTSDelta $ \d -> - addInodeCaches k . (++ ics) . catMaybes +storeInodeCaches k fs = withTSDelta $ \d -> + addInodeCaches k . catMaybes =<< liftIO (mapM (\f -> genInodeCache f d) fs) addInodeCaches :: Key -> [InodeCache] -> Annex ()