compute remote: get input files from other remotes

This needed some refactoring to avoid cycles, since Remote.Compute
cannot import Remote.List. Instead, it uses Annex.remotes. Which must be
populated by something else, but we know it has been, because something
is using Remote.Compute, which it must have found in the remote list,
which populates that.

In Remote.Compute, keyPossibilities' is called with all loggedLocations,
without the trustExclude DeadTrusted that keyLocations does. There is
another cycle there. This may be a problem if a dead repository is still
a remote.

This is missing cycle prevention, and it's certianly possible to make 2
files in the compute remote co-depend on one-another. Hopefully not in a
real world situation, but it an attacker could certainly do it. Cycle
prevention will need to be added to this.
This commit is contained in:
Joey Hess 2025-03-04 11:06:58 -04:00
parent b395bd4f56
commit 4e6324131d
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 84 additions and 37 deletions

View file

@ -32,14 +32,17 @@ import Config
import Config.Cost
import Remote.Helper.Special
import Remote.Helper.ExportImport
import Remote.List.Util
import Annex.SpecialRemote.Config
import Annex.UUID
import Annex.Content
import Annex.Tmp
import Annex.GitShaKey
import Annex.CatFile
import qualified Annex.Transfer
import Logs.MetaData
import Logs.EquivilantKeys
import Logs.Location
import Utility.Metered
import Utility.TimeStamp
import Utility.Env
@ -359,6 +362,8 @@ runComputeProgram
-> ComputeState
-> ImmutableState
-> (OsPath -> Annex (Key, Maybe (Either Git.Sha OsPath)))
-- ^ get input file's content, or Nothing when adding a computation
-- without actually performing it
-> (ComputeState -> OsPath -> NominalDiffTime -> Annex v)
-> Annex v
runComputeProgram (ComputeProgram program) state (ImmutableState immutablestate) getinputcontent cont =
@ -491,13 +496,34 @@ computeKey rs (ComputeProgram program) k _af dest p vc =
getinputcontent state f =
case M.lookup (fromOsPath f) (computeInputs state) of
Just inputkey -> case keyGitSha inputkey of
Nothing -> do
obj <- calcRepo (gitAnnexLocation inputkey)
-- XXX get input object when not present
return (inputkey, Just (Right obj))
Nothing ->
let retkey = do
obj <- calcRepo (gitAnnexLocation inputkey)
return (inputkey, Just (Right obj))
in ifM (inAnnex inputkey)
( retkey
, do
getinputcontent' f inputkey
retkey
)
Just gitsha ->
return (inputkey, Just (Left gitsha))
Nothing -> error "internal"
getinputcontent' f inputkey = do
remotelist <- Annex.getState Annex.remotes
locs <- loggedLocations inputkey
rs <- keyPossibilities' (IncludeIgnored False) inputkey locs remotelist
if null rs
then return ()
else void $ firstM (getinputcontentfrom f inputkey) rs
-- TODO cycle prevention
getinputcontentfrom f inputkey r = do
showAction $ "getting input " <> QuotedPath f
<> " from " <> UnquotedString (name r)
Annex.Transfer.download r inputkey (AssociatedFile (Just f))
Annex.Transfer.stdRetry Annex.Transfer.noNotification
computeskey state =
case M.keys $ M.filter (== Just k) (computeOutputs state) of