Opened 3 years ago

Closed 3 days ago

#12564 closed enhancement (not reproducible)

pkgman install *un*installs the package (if passed a local hpkg, no problem with remote hpkr's)

Reported by: ttcoder Owned by: bonefish
Priority: normal Milestone: R1
Component: Kits/Package Kit Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Has a Patch: no Platform: All

Description

dsuden keeps running into this vulnerability ever since I told him about "pkgman install", it's driving me nuts :-)

"Installing" a package which happens to be already installed, actually results in its de-installation (possibly because one of the performed steps, involves moving the "old" hpkg into a 'archive' subfolder of admnistrative, but both the "old" and "new" files are the same ?)

Furthermore, if said package is a dependancy of others, this obviously results in a cascade of consequences, ouch!

Reproducible "show and tell" session coming up below

----

Some naive enhancement ideas: if one of the package files passed to BPackageManager::Install() matches an already installed package for the specified repository...

  • reject the transaction as a whole ?
  • reject only that part of the transation ?
  • start applying the whole transaction, but abort/fail it at the stage of creating the .hpkg file within /system/packages, before the actual backup-to-archive stage (maybe might be as simple as tweaking an open() call, passing it the O_NOCLOBBER.. flag and throwing an exception if open() returns file-already-exists ?)
  • something else ?

Any of the above would result in cutting short the vulnerability exploit before the package gets uninstalled (and its dependancies if any) which would be great by me :-)

Change History (8)

comment:1 Changed 3 years ago by ttcoder

Simplified case, using lnlauncher:

Welcome to the Haiku shell.

~/Desktop> pkgman install lnlauncher  # initial install

Downloading repochecksum-1...done.
Validating checksum for Haiku...done.                                           
Downloading repochecksum-1...done.
Validating checksum for HaikuPorts...done.                                      
The following changes will be made:
  in system:
    install package lnlauncher-1.1.2-5 from repository HaikuPorts
Continue? [y/n] (y) : y
Downloading lnlauncher-1.1.2-5-x86_gcc2.hpkg...done.
Validating checksum for http://packages.haiku-os.org/haikuports/master/repo/x86_gcc2/current/packages/lnlauncher-1.1.2-5-x86_gcc2.hpkg...done.
[system] Applying changes ...
[system] Changes applied. Old activation state backed up in "state_2016-01-07_10:31:01"
[system] Cleaning up ...
[system] Done.

~/Desktop> pkgman install lnlauncher  # "second" install, from remote repo so not harmful:

Downloading repochecksum-1...done.
Validating checksum for Haiku...done.                                                                                                                                               
Downloading repochecksum-1...done.
Validating checksum for HaikuPorts...done.                                                                                                                                          
Nothing to do.  # perfect


# let's simulate Dane's actions:

~/Desktop> cp /system/packages/lnlauncher-1.1.2-5-x86_gcc2.hpkg  ./
~/Desktop> pkgman update ./lnlauncher-1.1.2-5-x86_gcc2.hpkg  # "second" install, with update: no harm
Downloading repochecksum-1...done.
Validating checksum for Haiku...done.                                           
Downloading repochecksum-1...done.
Validating checksum for HaikuPorts...done.                                      
Nothing to do.

~/Desktop> pkgman install ./lnlauncher-1.1.2-5-x86_gcc2.hpkg   # "second" install, with "install": ouch:
Downloading repochecksum-1...done.
Validating checksum for Haiku...done.                                           
Downloading repochecksum-1...done.
Validating checksum for HaikuPorts...done.                                      
The following changes will be made:
  in system:
    upgrade package lnlauncher-1.1.2-5 to 1.1.2-5 from local file  # one hint that Dane fails to see every time as he types "yes" anyway :-)
Continue? [y/n] (y) : y
[system] Applying changes ...
[system] Changes applied. Old activation state backed up in "state_2016-01-07_10:33:58"
[system] Cleaning up ...
failed to remove transaction directory: Directory not empty  # another symptom here
[system] Done.

~/Desktop> grep lnlauncher /system/packages/administrative/activated-packages  # ouch! package is no longer activated! (fortunately nobody depends on this package "lnlauncher" so no cascade)
~/Desktop> ls /system/packages/lnlauncher-1.1.2-5-x86_gcc2.hpkg  # the file is still there though
/system/packages/lnlauncher-1.1.2-5-x86_gcc2.hpkg
~/Desktop> grep lnlauncher /system/packages/administrative/state_2016-01-07_10\:33\:59/activated-packages 
lnlauncher-1.1.2-5-x86_gcc2.hpkg  # it was previously activated (after initial install)

EDIT:

Probably not important, but failed to mention that when Dane has this problem, which in his cases involves additional dependancies, the further cascade of de-activations of those dependancies comes up as a package_daemon alert box, a second or two after the initial session. It does not appear in terminal, within the pkgman session.

EDIT2: In the previous ticket #12560 we had brainstormed that I should change our roll-out code from "pkgman update" to "pkgman install", but it's clear I should *not* do that, pkgman install is a trapfall in 49856 :-) Let's enhance it to remove the vulnerability in the future.. And as to 49856 in prod. I'll find another workaround there.

Last edited 3 years ago by ttcoder (previous) (diff)

comment:2 Changed 3 years ago by bonefish

Given that pkgman says that the package will be upgraded, the solver has apparently correctly determined that the old package needs to be uninstalled and the new one installed. Looking at the package daemon side of things the general procedure looks good as well. Since old packages are moved to the old state directory first and new packages are moved from the transaction directory to the packages directory afterwards, a file name clash should not pose a problem.

The package file content creation looks good as well. So I guess that the error lies earlier (the non-empty transaction directory at the end suggests the same), i.e. during the initialization phase or even earlier. There's nothing that catches my eye, though. So some debugging is required. Unfortunately I don't have the time. :-/

comment:3 Changed 3 years ago by ttcoder

No pressure, can wait until the upcoming beta1 ..etc cycle or later -- the whole packaging system thing has made our life much easier already, but I'm always greedy for more silky-smoothness :-)

Forgot to mention, the "old state" directory does /not/ contain anything else than the old activated-packages text file.. I would have expected it to contain an instance of the lnlauncher.hpkg file; yet the only such copies are the 1) source hpkg file on Desktop, and 2) the (now deactivated) one in /system/packages

I could check the mod timestamp of the latter to determine if it's the old one (that thus failed to move?) or the new one

Also out of curiosity I looked at ChangePackageActivation to see what would happen if two packages of the same basename and version number were passed within the packagesToActivate argument and the packagesToDeactivate argument.. But in that case the code clearly adds it as activated. So if anything, this all indicates that the packagesToActivate variable does /not/ contain the lnlauncher hpkg I guess

EDIT: d'oh, just realized that this is what you were saying: if the activation-file creation got passed the wrong arguments, it means the problem occurs upstream of it, and that's where to orient the debugging efforts, got it

Last edited 3 years ago by ttcoder (previous) (diff)

comment:4 Changed 3 years ago by luroh

Sounds very much like #10914.

comment:5 in reply to:  4 Changed 3 years ago by bonefish

Replying to luroh:

Sounds very much like #10914.

Yes, the cause could be the same. When moving the package file manually to the packages directory everything happens in the package daemon, while when using pkgman the dependency solving happens on pkgman's side. It's quite possible that the dependency solving works fine in both cases and the error happens early in common package daemon side process.

comment:6 Changed 5 days ago by waddlesplash

Can you please retest this? #10914 was fixed long ago.

comment:7 Changed 4 days ago by ttcoder

Might be a while on my end: tied up for months.. But it would be ok to close this from our perspective: our use case has been different for eons: for the longest time, we've been using "pkgman update" instead of "pkgman install", for those rare cases where our built-in updater did not do the job. Henceforth we never saw that bug again.

comment:8 Changed 3 days ago by waddlesplash

Resolution: not reproducible
Status: newclosed

OK!

Note: See TracTickets for help on using tickets.