[config-package-dev] usrmerge and dpkg-divert
Geoffrey Thomas
geofft at ldpreload.com
Thu Jul 15 22:20:09 EDT 2021
>From yesterday's debian-devel thread
https://lists.debian.org/debian-devel/2021/07/msg00128.html
I learned that the dpkg maintainer does not consider the current
implementation of usrmerge supported by dpkg, and usrmerge is on by
default in Debian 11. Following some links,
https://wiki.debian.org/Teams/Dpkg/MergedUsr
claims that "dpkg-divert is currently broken by this approach."
As background, "usrmerge" is the situation where /bin and /usr/bin refer
to the same directory (and same for /lib and /usr/lib, etc.). On a
freshly-installed Bullseye system, this is implemented via symlinks:
geofft at bullseye:~$ ls -ld /*bin /lib*
lrwxrwxrwx 1 root root 7 Jul 15 21:21 /bin -> usr/bin
lrwxrwxrwx 1 root root 7 Jul 15 21:21 /lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jul 15 21:21 /lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Jul 15 21:21 /lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Jul 15 21:21 /libx32 -> usr/libx32
lrwxrwxrwx 1 root root 8 Jul 15 21:21 /sbin -> usr/sbin
The reason the dpkg maintainer says it's not supported is that dpkg
retains its original idea of whether files are in /bin or /usr/bin, for
example:
geofft at bullseye:~$ dpkg -S /bin/ls
coreutils: /bin/ls
geofft at bullseye:~$ dpkg -S /usr/bin/ls
dpkg-query: no path found matching pattern /usr/bin/ls
geofft at bullseye:~$ dpkg -S /bin/less
dpkg-query: no path found matching pattern /bin/less
geofft at bullseye:~$ dpkg -S /usr/bin/less
less: /usr/bin/less
The practical consequence of this is that it's possible to write a package
that diverts a file by its wrong name, which leads to confusing results.
For instance, here's a variant of debathena-bin-example-1.0 (from the
examples shipped with config-package-dev) where I've displaced /bin/less
instead of /usr/bin/less:
geofft at bullseye:~$ sudo dpkg -i debathena-bin-example_1.0_all.deb
Selecting previously unselected package debathena-bin-example.
(Reading database ... 35842 files and directories currently installed.)
Preparing to unpack debathena-bin-example_1.0_all.deb ...
Unpacking debathena-bin-example (1.0) ...
Setting up debathena-bin-example (1.0) ...
Adding 'diversion of /usr/bin/elinks to /usr/bin/elinks.debathena-orig by
debathena-bin-example'
Adding 'diversion of /bin/less to /bin/less.debathena-orig by
debathena-bin-example'
Adding 'diversion of /usr/share/man/man1/elinks.1.gz to
/usr/share/man/man1/elinks.debathena-orig.1.gz by debathena-bin-example'
Adding 'diversion of /usr/share/man/man1/less.1.gz to
/usr/share/man/man1/less.debathena-orig.1.gz by debathena-bin-example'
geofft at bullseye:~$ sudo apt install --reinstall less
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 0 not
upgraded.
Need to get 133 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://deb.debian.org/debian bullseye/main amd64 less amd64 551-2
[133 kB]
Fetched 133 kB in 0s (4,100 kB/s)
(Reading database ... 35854 files and directories currently installed.)
Preparing to unpack .../archives/less_551-2_amd64.deb ...
Unpacking less (551-2) over (551-2) ...
Setting up less (551-2) ...
Processing triggers for mailcap (3.69) ...
Processing triggers for man-db (2.9.4-2) ...
geofft at bullseye:~$ ls -l /usr/bin/less*
-rwxr-xr-x 1 root root 175816 Jul 5 2020 /usr/bin/less
-rwxr-xr-x 1 root root 105 Sep 11 2012 /usr/bin/less.debathena
-rwxr-xr-x 1 root root 175816 Jul 5 2020 /usr/bin/less.debathena-orig
[...]
As you can see, because the diversion was of the wrong path, dpkg didn't
prevent the less package from updating /usr/bin/less, and so it overwrote
the file we thought we owned, making the config package useless.
At least config-package-dev warns when you remove the package:
Removing debathena-bin-example (1.0) ...
Removing 'diversion of /usr/share/man/man1/less.1.gz to
/usr/share/man/man1/less.debathena-orig.1.gz by debathena-bin-example'
Removing 'diversion of /usr/share/man/man1/elinks.1.gz to
/usr/share/man/man1/elinks.debathena-orig.1.gz by debathena-bin-example'
*** OMINOUS WARNING ***: /bin/less is not linked to either less.debathena
or less.debathena-orig
Not removing diversion of /bin/less by debathena-bin-example
Removing 'diversion of /usr/bin/elinks to /usr/bin/elinks.debathena-orig
by debathena-bin-example'
but it leaves a mess to clean up by hand:
geofft at bullseye:~$ dpkg -S /bin/less
diversion by debathena-bin-example from: /bin/less
diversion by debathena-bin-example to: /bin/less.debathena-orig
geofft at bullseye:~$ ls -l /usr/bin/less*
-rwxr-xr-x 1 root root 175816 Jul 5 2020 /usr/bin/less
-rwxr-xr-x 1 root root 175816 Jul 5 2020 /usr/bin/less.debathena-orig
[...]
This only affects the case where you use the wrong path. As far as I can
tell, if you use the right path, everything is fine. However, a
consequence of usrmerge is that people aren't really supposed to care
about which path is "right."
I'm trying to figure out what, if anything, we should do about this. Some
options are:
- Add a NEWS entry + some docs saying that people need to be careful about
using the right path.
- Automatically try to determine whether you're using the wrong path. This
is trickier than it seems, because we do support the case where a config
package diverts a file that doesn't yet exist.
- For usrmerge-affected directories, on a usrmerged system, divert both
paths, and clean them both up on removal/undisplace. (I actually think
this might Just Work...)
- Push for a change into dpkg to sort this out, somehow. I do expect that
dpkg can be taught to figure its way around usrmerge, but I also expect
that the dpkg maintainer is very much uninterested in implementing it.
It's not clear to me whether the dpkg maintainer would be interested in
accepting a patch for it.
- Do nothing (or maybe update the website and the version in git with some
docs, but not the version in Bullseye).
Keep in mind that hard freeze is expected for this Saturday (see
https://release.debian.org/), so we'd very much need a freeze exception
for any option other than "do nothing."
Thoughts?
I'll go ahead and file a request to pre-approve some sort of change so we
get on the release team's radar, at least.
--
Geoffrey Thomas
https://ldpreload.com
geofft at ldpreload.com
More information about the config-package-dev
mailing list