phar-io / phive

The Phar Installation and Verification Environment (PHIVE)
https://phar.io
BSD 3-Clause "New" or "Revised" License
580 stars 45 forks source link

Error Report #209

Open ktomk opened 5 years ago

ktomk commented 5 years ago

Just stumbled over this while I wanted to gather some more information w/ my other reported issue (#208).

Given the phive.xml

<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
  <phar name="composer-require-checker" version="^2.0" installed="2.0.0" location="./tools/composer-require-checker" copy="false"/>
  <phar name="phpstan" version="^0.11.15" installed="0.11.15" location="./tools/phpstan" copy="false"/>
</phive>

and running this command:

$ ./bin/phive install --trust-gpg-keys D2CCAC42F6295E7D,8E730BA25823D8B5

where latest (stable) version of phive is ./bin/phive and all packages had been previously successfully installed but then were removed like:

$ rm /home/user/.phive/phars/composer-require-checker-2.0.0.phar
$ rm /home/tom/.phive/phars/phpstan-0.11.15.phar

w/o removing the symlinks:

./tools/composer-require-checker
./tools/phpstan

results in the following output/error:

Phive 0.13.0 - Copyright (C) 2015-2019 by Arne Blankerts, Sebastian Heuer and Contributors
[ERROR]    An error occurred while processing your request:

          file_get_contents(/home/tom/.phive/phars/composer-require-checker-2.0.0.phar): failed to open stream: No such file or directory

          #0 src/shared/PharRegistry.php(214)
          #1 unknown file(0): PharIo\Phive\Cli\Runner->errorHandler()
          #2 src/shared/PharRegistry.php(214): file_get_contents()
          #3 src/shared/PharRegistry.php(209): PharIo\Phive\PharRegistry->loadPharFile()
          #4 src/shared/PharRegistry.php(59): PharIo\Phive\PharRegistry->nodetoPhar()
          #5 src/shared/repository/LocalRepository.php(18): PharIo\Phive\PharRegistry->getPhars()
          #6 src/services/resolver/LocalAliasResolver.php(22): PharIo\Phive\LocalRepository->getReleasesByRequestedPhar()
          #7 src/services/resolver/RequestedPharResolverService.php(23): PharIo\Phive\LocalAliasResolver->resolve()
          #8 src/commands/install/InstallCommand.php(53): PharIo\Phive\RequestedPharResolverService->resolve()
          #9 src/commands/install/InstallCommand.php(42): PharIo\Phive\InstallCommand->resolveToRelease()
          #10 src/commands/install/InstallCommand.php(37): PharIo\Phive\InstallCommand->installRequestedPhar()
          #11 src/shared/cli/Runner.php(193): PharIo\Phive\InstallCommand->execute()
          #12 src/shared/cli/Runner.php(60): PharIo\Phive\Cli\Runner->execute()
          #13 (313): PharIo\Phive\Cli\Runner->run()
          #14 {main}

          Environment: PHP 7.4.0RC3
          Phive Version: 0.13.0

          This should not have happened and is most likely a bug.
          Please report it at https://github.com/phar-io/phive/issues, make sure you include
          the full output of this error message. Thank you!

(guess: invalid symlinks are the reason /e: removing the broken symlinks does not help)

ktomk commented 5 years ago

I could work around this by removing the installation db like;

$ rm -rf ~/.phive/phars

I could not work-around with --temporary for install command.

theseer commented 5 years ago

So the actual bug here is that we do not verify whether or not the phar database is actually in sync with reality, e.g. we currently trust the database.

The correct behavior would probably be to realize the file is missing and just download it again.

ktomk commented 5 years ago

Yes, I think on install if phive finds the phar in the database, it should check if the entry is orphaned and if so, just download again.

To check whether the phar exists on disk, phive should try to open the file for reading. Just checking w/ is_file() / is_readable() might return false albeit the phar file is there and is readable (SELinux etc., PHP accessing a file in the users home-dir). This would cause a constant re-download which is not wanted.

Also a higher level error message would be fine as well for me, like which phar (name only) according to which phive.xml file (and perhaps line number).

theseer commented 5 years ago

I'm not sure how trying to read the file would be any different from performing a file_exists in terms of SELinux? If the file is "invisible" to the PHP process, it should be invisible for either type of access. It would be pretty bizarre if I cannot test for the existence of a file but can read it if i know its path.

What am I missing?

theseer commented 5 years ago

Regarding error reporting: Certainly a re-download would require supporting output so a user knows what's going on.

ktomk commented 5 years ago

I just did remember an earlier issue (https://github.com/ktomk/pipelines/issues/1) where a file was checked readable before processing it. I then had a false negative.

I just checked it again. file_exists might work, the code in question used is_readable which returned false albeit it is possible to open the file.

theseer commented 5 years ago

That's a bizarre issue and setup. Why would the Security Context be configured like that? But okay, I'll keep it in mind :) Thanks for the pointer!

ktomk commented 5 years ago

Yeah, it took me a bit to understand what the issue for the user was.

I explained the reason to myself in the end like this: Because the process binary is php. That normally runs context of a webserver (so this would be a remote request) and therefore there are some safeguards regarding the users $HOME directory.

sebastianbergmann commented 5 years ago

Why would you use the PHP CLI SAPI executable, php, in a webserver context?

ktomk commented 5 years ago

@sebastianbergmann: I could only guess, but SELinux policy maybe makes no difference between the two for the case the user reported.