Package: dpkg
Version: 1.21.22

Exact text of error:

$ sudo dpkg -i etx8-web-2.0.0-29a5f09-b1443.deb
dpkg: warning: downgrading etx8-web from 2.1.0 to 2.0.0
(Reading database ... 35531 files and directories currently installed.)
Preparing to unpack etx8-web-2.0.0-29a5f09-b1443.deb ...
Checking upgrade/ downgrade compatibility...
Migrating network config in prerm
New version 2.0.0 < 2.1.0
Migrating network config 'down'.
found v46 network config: static 10.0.42.33/23 
Aborting migration - Static network configuration is incomplete. System will 
default to DHCP.
Archiving pre-downgrade network configs as '15-etx8-v4v6.network.backup'.
Current configuration: address='10.0.42.33/23', gateway=''; dns=''
dpkg: warning: old etx8-web package pre-removal script subprocess returned 
error exit status 1
dpkg: trying script from the new package instead ...
dpkg: ... it looks like that went OK
Unpacking etx8-web (2.0.0) over (2.1.0) ...

Incorrect behavior:

The package maintainer script workflow does not provide a mechanism for a newer 
installed package to prevent downgrading to an older version of the same 
package, for scenarios where the downgrade is impossible. In every case where 
one of the scripts from the currently installed package can signal an abort 
with a non-zero exit status, the workflow then runs the corresponding script 
from the target package. If that script succeeds, then installation continues. 
This is confirmed by reviewing the flowchart at 
https://www.debian.org/doc/debian-policy/ap-flowcharts.html.

When the target package is older than the currently installed package, its 
maintainer scripts have no knowledge of incompatible downgrade scenarios; they 
are likely to decide to proceed when there is no path to a working outcome.

Expected behavior:

During a downgrade, the older package should not have the final say in whether 
to abort or continue. That responsibility should always belong to the newer 
package, regardless of which is installed or being overwritten. This workflow 
seems to assume that nobody will ever need to revert to an older version of a 
package after they discover issues with a newer version. 

Suggested fixes:

Option 1: Allow different classes of exit status, that signal dpkg on whether 
to try the older version of a given script or not. For example, positive exit 
status could signal that dpkg should always try the alternate version of the 
script, while negative status could signal that dpkg should only try the 
alternate version of the script if the target version is greater than the 
installed version. The rational is that only a newer version should be expected 
to have knowledge of requirements that did not exist at the time the current 
version was released.  

Option 2: Offer an abort command that any maintainer script can call that 
definitively puts the in-progress installation into an abort state. All other 
maintainer scripts that run after abort has been signaled will get a parameter 
indicating that an abort is in progress, and they should only what they can to 
support as graceful of a bail-out as possible.

Versions of package dependencies: not applicable, dpkg is the chicken, packages 
are the eggs

Kernel & C library version: 

Linux voltserv-fe02 5.19.9-voltserver.1 #5 SMP Wed Jan 31 23:29:58 UTC 2024 
armv7l GNU/Linux
-rwxr-xr-x 1 root root 1102644 Apr 19 16:34 /lib/arm-linux-gnueabihf/libc.so.6

Details of the configuration of the program with the problem: None, the problem 
is with dpkg itself

Relevant hardware details: None, although FWIW we are running on ARM32

Additional detail:

Here is a summary of our specific case (some details have been factored out 
that are not relevant to the issue).

The latest version, 2.1, of our application that runs our hardware product on 
an embedded Linux system offers new network configuration. Specifically, 2.1 
allows users to omit the IP default gateway or DNS server, b/c our devices may 
be on an isolated management network does not have them. We have a new config 
file format to support all of the new options. During package install, 
maintainer scripts convert between old and new config file formats. 

There is no way to write a valid 2.0 configuration file without a default 
gateway or DNS server - the 2.0 UI would crash without them. In this case, our 
package maintainer scripts (2.1's prerm to be specific) looks for this 
scenario, and attempts to abort and tell the user what she needs to do before 
this downgrade is possible. However, dpkg then runs the 2.0 prerm script, which 
doesn't know about any of this. It succeeds, and then dpkg completes the 
downgrade, leaving behind a network config file that the newly installed 
version can't read. 

Show me:
* Start with any package at some version, e.g. 1.0. It can be an empty dummy 
package if you have one, as long as it has a maintainer script - e.g. preinst
* Create a 2.0 version of the package
* Let's say that 2.0 can not be downgraded at all to 1.0
* Update preinst to return exit with status 1
* generate the 2.0 .deb file
* install 1.0
* install 2.0
* install 1.0
* You are now on version 1.0. The exit 1 from version 2.0 was ignored.

Reply via email to