Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redownload pkgs when source hash verification fails #8500

Merged
merged 10 commits into from
Dec 27, 2022

Conversation

gbaz
Copy link
Collaborator

@gbaz gbaz commented Sep 29, 2022

Resolves #7451

(possibly)

Adds a call, when checking hashes in project planning, to also verify the hashes of existing tarballs downloaded from secure repos to make sure things haven't "changed out" as the might in the case of a mutable head.hackage or the like.

@gbaz gbaz marked this pull request as draft September 29, 2022 05:32
@gbaz gbaz marked this pull request as ready for review October 26, 2022 17:15
Copy link
Member

@Mikolaj Mikolaj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks like it may improve things. How to test it in CI?

if sz /= Sec.fileInfoLength (Sec.trusted fileInfo)
then return False
else Sec.compareTrustedFileInfo (Sec.trusted fileInfo) <$> Sec.computeFileInfo (Sec.Path file :: Sec.Path Sec.Absolute)
if infoVerified then return True else warn verbosity "whoops" >> return False) -- TODO
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you get around to this TODO, could you also make this more readable? The do in parens is hard to parse. E.g.,

Sec.withIndex repoSecure $ \callbacks -> do
  let verification = do
        fileInfo <- Sec.indexLookupFileInfo callbacks pkgid
        sz <- Sec.FileLength . fromInteger <$> getFileSize file
        if sz /= Sec.fileInfoLength (Sec.trusted fileInfo)
        then return False
        else Sec.compareTrustedFileInfo (Sec.trusted fileInfo) <$> Sec.computeFileInfo (Sec.Path file :: Sec.Path Sec.Absolute)
  infoVerified <- 
    verification
    `Sec.catchChecked` (\(e :: Sec.InvalidPackageException) -> warn verbosity (show e) >> return False)
    `Sec.catchChecked` (\(e :: Sec.VerificationError) -> warn verbosity (show e) >> return False)
  if infoVerified then return True else warn verbosity "whoops" >>  return False) -- TODO

which also changes the semantics slightly, probably resulting in a less puzzling warning if an exception occurs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for noticing the TODO. I refactored and cleaned up, but could not factor out into a let block as suggested -- the checked exceptions mechanism in hackage-security is fiddly, and trying some obvious things still resulted in a situation where the typechecker yelled at me. I'm sure it could be made to work, but I think the code after the refactor is sufficiently more clear.

@gbaz
Copy link
Collaborator Author

gbaz commented Oct 27, 2022

I don't think this is very CI testable. The best way I can think to test it is to fetch a package, then go into the cached downloads, mess with the downloaded package, and then attempt another action on it. I don't necessarily think adding a new test here makes much sense.

Copy link
Member

@Mikolaj Mikolaj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, just realigning the do made it much easier to parse. Too bad about no smart enough tests to merit including in CI. Thank you.

changelog.d/pr-8500 Outdated Show resolved Hide resolved
Co-authored-by: Hécate Moonlight <[email protected]>
@gbaz gbaz added the squash+merge me Tell Mergify Bot to squash-merge label Dec 24, 2022
@mergify mergify bot added the merge delay passed Applied (usually by Mergify) when PR approved and received no updates for 2 days label Dec 26, 2022
@mergify mergify bot merged commit e6c6dfc into master Dec 27, 2022
handleError act = do
res <- Safe.try act
case res of
Left e -> warn verbosity ("Error verifying fetched tarball " ++ file ++ ", will redownload: " ++ show (e :: SomeException)) >> pure False
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this error message triggered if file simply does not exist?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is, it's pretty urgent to fix, since it's causing a warning spam: #8571 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this function verifyFetchedTarball is called only in one place in the code, for all elements of repoTarballPkgsWithMetadataUnvalidated, which seems to contain ids of any packages that come from a secure repo, regardless of whether they were ever downloaded:

https://github.com/haskell/cabal/pull/8500/files#diff-2adae381a2eb2d8c804d5396694a431e1e3babd816a5d2408a62213cf774a893R929-R935

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A solution would be to move the partitioning wrt if a package is already downloaded (the block containing checkRepoTarballFetched) earlier and apply it to allPkgLocations instead of repoTarballPkgsWithoutMetadata. Only packages that are already downloaded would then be checked for RepoSecure and then verified. Does that make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, better, avoiding some filesystem IO, partition repoTarballPkgsWithMetadataUnvalidated wrt if a package is already downloaded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
attention: needs-review merge delay passed Applied (usually by Mergify) when PR approved and received no updates for 2 days squash+merge me Tell Mergify Bot to squash-merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

'cabal build' fails to build package from head.hackage (due to "Downloading" being missing)
4 participants