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 ; \