Hi Aurelien and Sven,

On Wed, Jan 24, 2024 at 09:19:12PM +0100, Aurelien Jarno wrote:
> On 2024-01-23 17:40, Helmut Grohne wrote:
> > Conflicting runtime dynamic linkers between multiarch packages
> > ==============================================================
> > 
> > Some architecture combinations such as s390, powerpc, hppa, m68k,
> > mipsn32, and hurd-i386 or alpha, i386, sh4, and sparc have conflicting
> > runtime dynamic loaders. In theory this violates Multi-Arch: same, but
> > there is basically nothing we can do about this and dropping Multi-Arch:
> > same from the packages would completely break any kind of multiarch
> > setup. There is little we can do here and this is also unrelated to
> > DEP17.
> 
> We tried to add conflicts for those, like it's done for the multilib
> packages, but at the time the infrastructure exploded (see #745552). I
> don't remember the details, but I guess it was either dak or
> dose-builddebcheck.

Yeah, I also remember something like that. It's not the first time I
trip into this. "There is little we can do here" still counts.

> I guess the symlink in the maintainer script could indeed work. I am not
> sure why it has been done like that, it was part of the multiarch
> patchset from Steve Langasek more than 10 years ago.

Practically speaking, it appears to work rather well. On the flip side,
I also thought that way of my first patch. ;)

> Note however that the those packages are used by cross-toolchain-base
> (which builds them from glibc-source) and mangled to install them in the
> cross path. See for instance libc6-amd64-x32-cross. For such cases, we
> probably do want to keep the dynamic linker symlink, as those packages
> do not have maintainer scripts.

I don't think those -$arch-cross packages need the runtime dynamic
linker at all. Unlike the libc6-$multilib packages, we don't use
-$arch-cross packages to actaully run any binary. Simply not installing
it might just work in practice.

So here is an updated patch with a few notes:
 * This patch moves all the files including the runtime dynamic linker
   in the main multiarch library. Therefore, this patch needs to be
   synced with the corresponding base-files change to add the aliasing
   symlinks or debootstrap breaks. In other words: Don't upload this
   yet.
 * As mentioned earlier, only the multiarch packages install the runtime
   dynamic linker via data.tar. All the multilib packages install it via
   maintainer scripts now.
 * When installing libc6-x32, /libx32 will be created because partial
   upgrades might otherwise be broken. Removing libc6-x32 will not
   remove /libx32 though. I suggest fixing this in base-files by
   installing a trigger interest in /usr/libx32 and having
   base-files.postinst create/remove /libx32 as needed. This way, we
   centralize the management of aliasing links into base-files. libx32
   only serves as an example here and it works the same way for any
   other non-essential multilib directory. Do you agree with the
   approach?
 * The multilib packages install a trigger interest on the runtime
   dynamic linker such that they notice when a multiarch package deletes
   it and can then recreate it as needed. Thus the multiarch packages do
   not have to pay attention to a possibly installed multilib package
   when they are removed.
 * I've tried quite a few multiarch upgrades involving amd64 and i386
   using dpkg --auto-deconfigure --unpack with various packages and even
   cross grading libc6-x32 from :i386 to :amd64 during the upgrade.
   While dpkg --verify was occasionally unhappy during a partial upgrade
   (where half-unpacked packages were around), once no package was
   half-installed, dpkg --verify was also happy again in all attempts. I
   did not come up with a systematic enumeration of possible upgrade
   scenarios though.
 * The patch works will deboostrap/cdebootstrap/mmdebstrap (in
   combination with more patches including base-files, bash, dash and
   util-linux).
 * The change to install ldconfig to /usr/sbin can be uploaded right
   away. It's limited to debian/debhelper.in/libc-bin.install and
   debian/debhelper.in/libc-bin.lintian-overrides and doesn't contribute
   much diff, so doing it later is fine as well.

I hope you don't manage to punch holes into my theory this time around.

Helmut
diff --minimal -Nru glibc-2.37/debian/changelog glibc-2.37/debian/changelog
--- glibc-2.37/debian/changelog 2024-01-23 07:13:18.000000000 +0100
+++ glibc-2.37/debian/changelog 2024-01-19 15:56:06.000000000 +0100
@@ -1,3 +1,10 @@
+glibc (2.37-14.1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * DEP17: Move files to /usr. (Closes: #-1)
+
+ -- Helmut Grohne <hel...@subdivi.de>  Fri, 19 Jan 2024 15:56:06 +0100
+
 glibc (2.37-14) unstable; urgency=medium
 
   [ Aurelien Jarno ]
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-alt.install 
glibc-2.37/debian/debhelper.in/libc-alt.install
--- glibc-2.37/debian/debhelper.in/libc-alt.install     2022-09-22 
22:06:02.000000000 +0200
+++ glibc-2.37/debian/debhelper.in/libc-alt.install     2024-01-19 
15:56:06.000000000 +0100
@@ -1,6 +1,5 @@
 # This file is used for biarch libraries.
-TMPDIR/RTLDDIR/*.so* RTLDDIR
-TMPDIR/SLIBDIR/*.so* SLIBDIR
+TMPDIR/SLIBDIR/*.so* /usrSLIBDIR
 TMPDIR/LIBDIR/gconv/* LIBDIR/gconv/
 
 TMPDIR/etc/ld.so.conf.d /etc
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-alt.postinst 
glibc-2.37/debian/debhelper.in/libc-alt.postinst
--- glibc-2.37/debian/debhelper.in/libc-alt.postinst    1970-01-01 
01:00:00.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-alt.postinst    2024-01-19 
15:56:06.000000000 +0100
@@ -0,0 +1,31 @@
+#!/bin/sh
+set -e
+
+# begin-remove-after: released:forky
+if [ "$1" = configure ]; then
+    # These symbolic links are either included in base-files or created by
+    # base-files via triggers, but we also create them to avoid a versioned
+    # dependency on base-files. Cleanup will be handled by base-files.
+    if ! [ -h "$DPKG_ROOTRTLDDIR" ]; then
+        ln -s "usrRTLDDIR" "$DPKG_ROOTRTLDDIR"
+    fi
+    if ! [ -h "$DPKG_ROOTSLIBDIR" ]; then
+        ln -s usrSLIBDIR "$DPKG_ROOTSLIBDIR"
+    fi
+fi
+# end-remove-after
+
+if [ "$1" = configure -o "$1" = triggered ] && ! [ -h 
"$DPKG_ROOT/usrRTLDDIR/RTLD_SO" ]; then
+    # In principle, this package should contain this link, but it also is
+    # contained in the multiarch libc package. To avoid a conflict and the need
+    # for declaring Replaces (which work badly with the /usr-move due to
+    # aliasing), we manually create this link whenever we are installed or
+    # upgraded or the multiarch libc is installed, upgraded or importantly
+    # removed. The link target is given as absolute without /usr. The runtime
+    # linker directory is always one level deep, so we can simply prepend "..".
+    ln -s ..RTLD_TARGET "$DPKG_ROOT/usrRTLDDIR/RTLD_SO"
+fi
+
+#DEBHELPER#
+
+exit 0
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-alt.postrm 
glibc-2.37/debian/debhelper.in/libc-alt.postrm
--- glibc-2.37/debian/debhelper.in/libc-alt.postrm      2024-01-23 
07:13:18.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-alt.postrm      2024-01-19 
15:56:06.000000000 +0100
@@ -2,13 +2,12 @@
 set -e
 
 if [ "$1" = remove ]; then
-    # Native multiarch packages declare a Replaces: on the corresponding
-    # biarch package. Therefore if both a biarch package and the corresponding
-    # multiarch package are installed, then the multiarch package is removed,
-    # and then the biarch package is removed, the dynamic linker symlink
-    # becomes a dangling symlink. Remove it in that case.
-    if [ -h RTLDDIR/RTLD_SO ] && [ ! -f RTLDDIR/RTLD_SO ]; then
-        rm RTLDDIR/RTLD_SO
+    # We manually installed this link in postinst if missing. It is also
+    # installed by the native multiarch package as a proper file. We have
+    # to remove it if we are the last package to provide it. Detect that
+    # situation by checking for a dangling link.
+    if [ -h /usrRTLDDIR/RTLD_SO ] && [ ! -f /usrRTLDDIR/RTLD_SO ]; then
+        rm /usrRTLDDIR/RTLD_SO
     fi
 fi
 
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-alt.preinst 
glibc-2.37/debian/debhelper.in/libc-alt.preinst
--- glibc-2.37/debian/debhelper.in/libc-alt.preinst     2024-01-23 
07:13:18.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-alt.preinst     2024-01-19 
15:56:06.000000000 +0100
@@ -1,6 +1,7 @@
 #!/bin/sh
 set -e
 
+# begin-remove-after: released:forky
 # We create the top-level lib symlink on merged-usr systems, so that we can
 # cover cases where for example libc-i386 on amd64 is installed and then 
removed
 # (which deletes the symlink too). Note that we only suppor the simplest case,
@@ -14,11 +15,11 @@
         # If it has not, is a directory already there? Half-merged systems are
         # the problem of usrmerge, simply ignore them here.
         if [ ! -L SLIBDIR ] && [ ! -d SLIBDIR ]; then
-            mkdir -p /usrSLIBDIR
             ln -s usrSLIBDIR SLIBDIR
         fi
     fi
 fi
+# end-remove-after
 
 #DEBHELPER#
 
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-alt.triggers 
glibc-2.37/debian/debhelper.in/libc-alt.triggers
--- glibc-2.37/debian/debhelper.in/libc-alt.triggers    1970-01-01 
01:00:00.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-alt.triggers    2024-01-19 
15:56:06.000000000 +0100
@@ -0,0 +1,3 @@
+# Monitor the dynamic linker from the native multiarch package that is shared
+# with us.
+interest-noawait /usrRTLDDIR/RTLD_SO
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-bin.install 
glibc-2.37/debian/debhelper.in/libc-bin.install
--- glibc-2.37/debian/debhelper.in/libc-bin.install     2024-01-23 
07:13:18.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-bin.install     2024-01-19 
15:56:06.000000000 +0100
@@ -4,7 +4,7 @@
 debian/local/etc/nsswitch.conf usr/share/libc-bin
 debian/local/etc/nss etc/default
 posix/gai.conf etc
-sbin/ldconfig sbin
+sbin/ldconfig usr/sbin
 usr/bin/getconf
 usr/bin/getent
 usr/bin/iconv
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-bin.lintian-overrides 
glibc-2.37/debian/debhelper.in/libc-bin.lintian-overrides
--- glibc-2.37/debian/debhelper.in/libc-bin.lintian-overrides   2024-01-23 
07:13:18.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-bin.lintian-overrides   2024-01-19 
15:56:06.000000000 +0100
@@ -1,10 +1,10 @@
 # ldconfig must be executable even when the libc is not configured, and
 # thus must be linked statically
-statically-linked-binary sbin/ldconfig
-shared-library-lacks-prerequisites [sbin/ldconfig]
+statically-linked-binary usr/sbin/ldconfig
+shared-library-lacks-prerequisites [usr/sbin/ldconfig]
 
 # these manpages are provided by the manpages package
-no-manual-page [sbin/ldconfig]
+no-manual-page [usr/sbin/ldconfig]
 no-manual-page [usr/bin/getent]
 no-manual-page [usr/bin/iconv]
 no-manual-page [usr/bin/ld.so]
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-udeb.install 
glibc-2.37/debian/debhelper.in/libc-udeb.install
--- glibc-2.37/debian/debhelper.in/libc-udeb.install    2024-01-23 
07:13:18.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-udeb.install    2024-01-19 
15:56:06.000000000 +0100
@@ -1,11 +1,11 @@
-lib*/ld*.so*
-lib/*/ld*.so*
-lib/*/libm.so.*
-lib/*/libmvec.so.*
-lib/*/libdl.so.*
-lib/*/libresolv.so.*
-lib/*/libc.so.*
-lib/*/librt.so.*
-lib/*/libpthread.so.*
-lib/*/libnss_dns.so.*
-lib/*/libnss_files.so.*
+RTLDDIR/ld*.so* /usrRTLDDIR
+SLIBDIR/ld*.so* /usrSLIBDIR
+SLIBDIR/libm.so.* /usrSLIBDIR
+SLIBDIR/libmvec.so.* /usrSLIBDIR
+SLIBDIR/libdl.so.* /usrSLIBDIR
+SLIBDIR/libresolv.so.* /usrSLIBDIR
+SLIBDIR/libc.so.* /usrSLIBDIR
+SLIBDIR/librt.so.* /usrSLIBDIR
+SLIBDIR/libpthread.so.* /usrSLIBDIR
+SLIBDIR/libnss_dns.so.* /usrSLIBDIR
+SLIBDIR/libnss_files.so.* /usrSLIBDIR
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc-udeb.install.hurd-i386 
glibc-2.37/debian/debhelper.in/libc-udeb.install.hurd-i386
--- glibc-2.37/debian/debhelper.in/libc-udeb.install.hurd-i386  2024-01-23 
07:13:18.000000000 +0100
+++ glibc-2.37/debian/debhelper.in/libc-udeb.install.hurd-i386  2024-01-19 
15:56:06.000000000 +0100
@@ -1,14 +1,14 @@
-lib*/ld*.so*
-lib/*/ld*.so*
-lib/*/libm.so.*
-lib/*/libmvec.so.*
-lib/*/libdl.so.*
-lib/*/libresolv.so.*
-lib/*/libc.so.*
-lib/*/libutil.so.*
-lib/*/librt.so.*
-lib/*/libpthread.so.*
-lib/*/libnss_dns.so.*
-lib/*/libnss_files.so.*
-lib/*/libmachuser.so.*
-lib/*/libhurduser.so.*
+RTLDDIR/ld*.so* /usrRTLDDIR
+SLIBDIR/ld*.so* /usrSLIBDIR
+SLIBDIR/libm.so.* /usrSLIBDIR
+SLIBDIR/libmvec.so.* /usrSLIBDIR
+SLIBDIR/libdl.so.* /usrSLIBDIR
+SLIBDIR/libresolv.so.* /usrSLIBDIR
+SLIBDIR/libc.so.* /usrSLIBDIR
+SLIBDIR/libutil.so.* /usrSLIBDIR
+SLIBDIR/librt.so.* /usrSLIBDIR
+SLIBDIR/libpthread.so.* /usrSLIBDIR
+SLIBDIR/libnss_dns.so.* /usrSLIBDIR
+SLIBDIR/libnss_files.so.* /usrSLIBDIR
+SLIBDIR/libmachuser.so.* /usrSLIBDIR
+SLIBDIR/libhurduser.so.* /usrSLIBDIR
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc.install 
glibc-2.37/debian/debhelper.in/libc.install
--- glibc-2.37/debian/debhelper.in/libc.install 2024-01-23 07:13:18.000000000 
+0100
+++ glibc-2.37/debian/debhelper.in/libc.install 2024-01-19 15:56:06.000000000 
+0100
@@ -1,4 +1,4 @@
 etc/ld.so.conf.d
-lib*/ld*.so*
-lib/*/*.so*
+RTLDDIR/ld*.so* /usrRTLDDIR
+SLIBDIR/*.so* /usrSLIBDIR
 usr/lib/*/gconv
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc.postrm 
glibc-2.37/debian/debhelper.in/libc.postrm
--- glibc-2.37/debian/debhelper.in/libc.postrm  2024-01-23 07:13:18.000000000 
+0100
+++ glibc-2.37/debian/debhelper.in/libc.postrm  2024-01-19 15:56:06.000000000 
+0100
@@ -2,18 +2,8 @@
 set -e
 
 if [ "$1" = remove ]; then
-    # When both the multiarch and the corresponding biarch packages are
-    # installed, removing the multiarch package will remove the dynamic
-    # linker. Recreate it in the postinst.
-    ARCH=${DPKG_MAINTSCRIPT_ARCH}
-    target=$(dpkg-query -L LIBC-${ARCH} 2>/dev/null | grep -E 
'/lib.+/(ld\.so|RTLD_SO)$' || true)
-    if [ -f "$target" ] && ! [ -f RTLDDIR/RTLD_SO ] ; then
-        ln -sf ${target#RTLDDIR/} RTLDDIR/RTLD_SO
-    fi
-fi
-
-if [ "$1" = deconfigure ]; then
-    :; # blah, do something useful with ldso
+    # Remove DEP17 M8 protective diversion
+    dpkg-divert --quiet --remove --no-rename --divert 
"RTLDDIR/RTLD_SO.usr-is-merged" "RTLDDIR/RTLD_SO"
 fi
 
 #DEBHELPER#
diff --minimal -Nru glibc-2.37/debian/debhelper.in/libc.preinst 
glibc-2.37/debian/debhelper.in/libc.preinst
--- glibc-2.37/debian/debhelper.in/libc.preinst 2024-01-23 07:13:18.000000000 
+0100
+++ glibc-2.37/debian/debhelper.in/libc.preinst 2024-01-19 15:56:06.000000000 
+0100
@@ -295,6 +295,25 @@
     fi
 fi
 
+# begin-remove-after: released:forky
+# Add DEP17 M4 protective diversions. These should be added by base-files, but
+# we want to avoid Pre-Depends: base-files (>= trixie) and therefore add them
+# for base-files. As bookworm's base-files installs bin lib and sbin, the only
+# directory we may miss is the one containing the runtime linker when it is not
+# /lib.
+if [ "$1" = install -o "$1" = upgrade ] && [ "RTLDDIR" != "/lib" ]; then
+    dpkg-divert --quiet --add --no-rename --package base-files --divert 
"RTLDDIR.usr-is-merged" "RTLDDIR"
+fi
+# end-remove-after
+
+# Add DEP17 M8 protective diversions for the runtime dynamic linker. It is
+# installed in both libc (multiarch) and libc-alt (multilib) amounting to a
+# move and thus DEP17 P1 problem. This diversion should be removed by forky's
+# libc.postinst.
+if [ "$1" = install ] || [ "$1" = upgrade ]; then
+    dpkg-divert --quiet --add --no-rename --divert 
"RTLDDIR/RTLD_SO.usr-is-merged" "RTLDDIR/RTLD_SO"
+fi
+
 #DEBHELPER#
 
 if [ -n "$preversion" ]; then
diff --minimal -Nru glibc-2.37/debian/rules glibc-2.37/debian/rules
--- glibc-2.37/debian/rules     2024-01-23 07:13:18.000000000 +0100
+++ glibc-2.37/debian/rules     2024-01-19 15:56:06.000000000 +0100
@@ -91,6 +91,7 @@
 mvec = no
 
 rtld_so=$(shell awk 'BEGIN {FS="="} /^ld\.so-version/ {print $$2}' 
$(DEB_BUILDDIR)/soversions.mk)
+rtld_target=$(shell readlink $(debian-tmp)$(rtlddir)/$(rtld_so))
 libc_so=$(shell awk 'BEGIN {FS="="} /^libc\.so-version/ {print "libc.so"$$2}' 
$(DEB_BUILDDIR)/soversions.mk)
 
 BASE_CC = gcc
diff --minimal -Nru glibc-2.37/debian/rules.d/debhelper.mk 
glibc-2.37/debian/rules.d/debhelper.mk
--- glibc-2.37/debian/rules.d/debhelper.mk      2024-01-23 07:13:18.000000000 
+0100
+++ glibc-2.37/debian/rules.d/debhelper.mk      2024-01-19 15:56:06.000000000 
+0100
@@ -30,6 +30,14 @@
        dh_installsystemd -p$(curpass)
        dh_installdocs -p$(curpass) 
        dh_lintian -p $(curpass)
+
+       # Ensure that symlinks resolve even when /usr is unmerged.
+       set -e; \
+       find "debian/$(curpass)" \( -lname "*../lib*" -o -lname "/lib*" \) 
-printf "%p*%l\n" | \
+       while IFS='*' read -r p l; do \
+         ln -svf "$${l%%/lib*}/usr/lib$${l#*/lib}" "$$p"; \
+       done
+
        dh_link -p$(curpass)
        dh_bugfiles -p$(curpass)
 
@@ -89,6 +97,14 @@
        dh_installdirs -p$(curpass)
        dh_install -p$(curpass)
        dh_strip -p$(curpass)
+
+       # Ensure that symlinks resolve even when /usr is unmerged.
+       set -e; \
+       find "debian/$(curpass)" \( -lname "*../lib*" -o -lname "/lib*" \) 
-printf "%p*%l\n" | \
+       while IFS='*' read -r p l; do \
+         ln -svf "$${l%%/lib*}/usr/lib$${l#*/lib}" "$$p"; \
+       done
+
        dh_link -p$(curpass)
        
        # when you want to install extra packages, use extra_pkg_install.
@@ -153,6 +169,8 @@
        slibdir=$(call xx,slibdir) ; \
        rtlddir=$(call xx,rtlddir) ; \
        curpass=$(curpass) ; \
+       rtld_so=$(rtld_so) ; \
+       rtld_target=$(rtld_target) ; \
        templates="libc-dev" ;\
        pass="" ; \
        suffix="" ;\
@@ -181,6 +199,8 @@
                -e "s#RTLDDIR#$$rtlddir#g" \
                -e "s#SLIBDIR#$$slibdir#g" \
                -e "s#LIBDIR#$$libdir#g" \
+               -e "s#RTLD_SO#$$rtld_so#g" \
+               -e "s#RTLD_TARGET#$$rtld_target#g" \
                -e "/gdb/d" \
                -e "/audit/d" \
              $$t; \
@@ -194,6 +214,7 @@
        rtlddir=$(call xx,rtlddir) ; \
        curpass=$(curpass) ; \
        rtld_so=$(rtld_so) ; \
+       rtld_target=$(rtld_target) ; \
        case "$$curpass:$$slibdir" in \
          libc:*) \
            templates="libc libc-dev libc-udeb" \
@@ -217,6 +238,7 @@
            sed -e "s#SLIBDIR#$$slibdir#g" -i $$t; \
            sed -e "s#LIBDIR#$$libdir#g" -i $$t; \
            sed -e "s#RTLD_SO#$$rtld_so#g" -i $$t ; \
+           sed -e "s#RTLD_TARGET#$$rtld_target#g" -i $$t ; \
            $(if $(filter $(call xx,mvec),no),sed -e "/libmvec/d" -e 
"/libm-\*\.a/d" -i $$t ;) \
            $(if $(filter-out $(DEB_HOST_ARCH_OS),linux),sed -e "/gdb/d" -i $$t 
;) \
          done ; \

Reply via email to