On 2011-08-13 23:17 +0200, Sven Joachim wrote: > On 2011-08-13 22:14 +0200, Jonathan Nieder wrote: > >> Sven Joachim wrote: >> >>> - link_name="debian/tmp-$(curpass)/lib/$$rtld_so" ; \ >>> + link_name="debian/tmp-$(curpass)/$(call xx,rtlddir)/$$rtld_so" ; \ >>> target="$(call xx,slibdir)/$$(readlink >>> debian/tmp-$(curpass)/$(call xx,slibdir)/$$rtld_so)" ; \ >>> + mkdir -p debian/tmp-$(curpass)/$(call xx,rtlddir); \ >>> ln -s $$target $$link_name ; \
I have completely dropped this part. Installing into debian/tmp-$(curpass)/lib is fine at this stage, no matter what the final destination is. >> Do I understand correctly that this is this a no-op (to prepare for >> patch 5)? > > Ouch. It should not have been; I made a mistake while rebasing the > patches, because the target dir in libc.install needs to be set to > RTLDDIR, not to /lib. So I install into both RTLDDIR and /lib, as in the old patch 5. >> [...] >>> @@ -384,6 +404,13 @@ fi >>> #DEBHELPER# >>> >>> if [ -n "$preversion" ]; then >>> + if test -L /lib64; then >>> + case ${DPKG_MAINTSCRIPT_ARCH:-$(dpkg --print-architecture)} in >>> + amd64 | ppc64 | sparc64 | s390x) >>> + remove_lib64_symlink ;; >>> + esac >>> + fi >> >> If DPKG_MAINTSCRIPT_ARCH isn't set for some reason, this gives the >> wrong value. Would it be possible to introduce a variable in >> debian/rules.d/debhelper.mk so the right value can be cooked in at >> build time? > > Probably, but I guess it does not matter in practice. > DPKG_MAINTSCRIPT_ARCH is exported by dpkg since 1.15.4, and old dpkg > versions don't support multiarch so you have to do something totally > weird to install a foreign libc6. I don't feel the need to do anything about it and leave it to Aurelien if he thinks this is necessary. >> Maybe it would be possible to mv /lib64 somewhere and loudly let the >> admin know about it if it contains anything more than the dynamic >> linker. > > Good idea. Something like that: > > aside=$(mktemp -d /lib64-moved-by-libc6-prerm.XXXXXX) > echo "Moving /lib64 aside to $aside" > mv /lib64 $aside See patches 5 and 6 in the new attached series. > I have some private undertakings tomorrow, will likely send a new patch > series on Monday, unless somebody beats me to it. The biggest change compared to the previous one is the new patch 6 which tries to check that there is at least one free inode. Namely, if there aren't any, the sequence rm -f /lib64 $interpreter /bin/mkdir /lib64 $interpreter /bin/ln -s $ldfile RTLD_SO will fail in the third command which is rather embarrassing. This is of course far from perfect, if another process runs riot and creates files rapidly, you can still lose. Also, that part isn't really tested at all (except that it works when there are no ENOSPC problems). I have lightly tested unpack failures by introducing a file conflict with another package, they do at least not lead to immediate disaster. The only problem that I see is that if unpacking fails during upgrade and you then downgrade to an older _major_ eglibc version, /lib64/ld-linux-x86-64.so.2 becomes a dangling symlink. I don't think there is much which can be done about this. Cheers, Sven
>From 6ead53c51dac3ef8aa77b96b8c8f1a647f654a6d Mon Sep 17 00:00:00 2001 From: Sven Joachim <svenj...@gmx.de> Date: Thu, 11 Aug 2011 17:15:03 +0200 Subject: [PATCH 1/6] Don't create /lib64 and /usr/lib64 symlinks --- debian/sysdeps/amd64.mk | 3 --- debian/sysdeps/kfreebsd-amd64.mk | 6 ------ debian/sysdeps/ppc64.mk | 6 ------ debian/sysdeps/s390x.mk | 6 ------ debian/sysdeps/sparc64.mk | 6 ------ 5 files changed, 0 insertions(+), 27 deletions(-) diff --git a/debian/sysdeps/amd64.mk b/debian/sysdeps/amd64.mk index c99dea4..67000a5 100644 --- a/debian/sysdeps/amd64.mk +++ b/debian/sysdeps/amd64.mk @@ -1,10 +1,7 @@ libc_rtlddir = /lib64 extra_config_options = --enable-multi-arch -# /lib64 and /usr/lib64 are provided by glibc instead base-files: #259302. define libc6_extra_pkg_install -ln -sf /lib debian/$(curpass)/lib64 -ln -sf lib debian/$(curpass)/usr/lib64 make -C debian/local/memcpy-wrapper install -m 755 -o root -g root -d debian/libc6/$(libdir)/libc diff --git a/debian/sysdeps/kfreebsd-amd64.mk b/debian/sysdeps/kfreebsd-amd64.mk index 261cbda..635b72d 100644 --- a/debian/sysdeps/kfreebsd-amd64.mk +++ b/debian/sysdeps/kfreebsd-amd64.mk @@ -1,12 +1,6 @@ # Main library extra_config_options = --disable-compatible-utmp --disable-multi-arch -# /lib64 and /usr/lib64 are provided by glibc instead base-files: #259302. -define libc0.1_extra_pkg_install -ln -sf /lib debian/$(curpass)/lib64 -ln -sf lib debian/$(curpass)/usr/lib64 -endef - # build 32-bit (i386) alternative library EGLIBC_PASSES += i386 DEB_ARCH_REGULAR_PACKAGES += libc0.1-i386 libc0.1-dev-i386 diff --git a/debian/sysdeps/ppc64.mk b/debian/sysdeps/ppc64.mk index 98cea4b..c8d2509 100644 --- a/debian/sysdeps/ppc64.mk +++ b/debian/sysdeps/ppc64.mk @@ -1,12 +1,6 @@ libc_rtlddir = /lib64 extra_config_options = --enable-multi-arch -# /lib64 and /usr/lib64 are provided as symlinks -define libc6_extra_pkg_install -ln -sf /lib debian/$(curpass)/lib64 -ln -sf lib debian/$(curpass)/usr/lib64 -endef - # build 32-bit (powerpc) alternative library EGLIBC_PASSES += powerpc DEB_ARCH_REGULAR_PACKAGES += libc6-powerpc libc6-dev-powerpc diff --git a/debian/sysdeps/s390x.mk b/debian/sysdeps/s390x.mk index acb5c41..b3707cd 100644 --- a/debian/sysdeps/s390x.mk +++ b/debian/sysdeps/s390x.mk @@ -1,11 +1,5 @@ libc_rtlddir = /lib64 -# /lib64 and /usr/lib64 are provided by glibc instead base-files: #259302. -define libc6_extra_pkg_install -ln -sf /lib debian/$(curpass)/lib64 -ln -sf lib debian/$(curpass)/usr/lib64 -endef - # build 32-bit (s390) alternative library EGLIBC_PASSES += s390 DEB_ARCH_REGULAR_PACKAGES += libc6-s390 libc6-dev-s390 diff --git a/debian/sysdeps/sparc64.mk b/debian/sysdeps/sparc64.mk index 3b6771b..b224abb 100644 --- a/debian/sysdeps/sparc64.mk +++ b/debian/sysdeps/sparc64.mk @@ -1,9 +1,3 @@ extra_config_options = --disable-multi-arch libc_rtlddir = /lib64 libc_extra_cflags = -mcpu=ultrasparc - -# /lib64 and /usr/lib64 are provided by glibc instead base-files: #259302. -define libc6_extra_pkg_install -ln -sf lib debian/$(curpass)/lib64 -ln -sf lib debian/$(curpass)/usr/lib64 -endef -- 1.7.5.4
>From 9a37761826bd3069efa6c613c55fd5633f6aeb5c Mon Sep 17 00:00:00 2001 From: Sven Joachim <svenj...@gmx.de> Date: Thu, 11 Aug 2011 18:28:37 +0200 Subject: [PATCH 2/6] Install the dynamic linker into RTLDDIR as well as /lib Installing into both locations makes it easier to support downgrades. It also means that dpkg will fail to unpack our package if RTLDDIR=/lib64 and /lib64 is a symlink to /lib. Which is probably a good thing since that symlink has to go away. Note that this is a no-op on architectures where RTLDDIR=/lib. --- debian/debhelper.in/libc.install | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/debian/debhelper.in/libc.install b/debian/debhelper.in/libc.install index e377d64..0947513 100644 --- a/debian/debhelper.in/libc.install +++ b/debian/debhelper.in/libc.install @@ -1,4 +1,5 @@ TMPDIR/lib/*.so* /lib +TMPDIR/lib/*.so* RTLDDIR TMPDIR/SLIBDIR/*.so* SLIBDIR TMPDIR/LIBDIR/gconv/* LIBDIR/gconv -- 1.7.5.4
>From 4c25216a4e8b7d6ead202912cde048bdc8160389 Mon Sep 17 00:00:00 2001 From: Sven Joachim <svenj...@gmx.de> Date: Sat, 13 Aug 2011 10:22:21 +0200 Subject: [PATCH 3/6] Remove the /lib64 symlink on upgrades Only necessary on amd64, ppc64, sparc64 and s390x. --- debian/debhelper.in/libc.preinst | 30 ++++++++++++++++++++++++++++++ 1 files changed, 30 insertions(+), 0 deletions(-) diff --git a/debian/debhelper.in/libc.preinst b/debian/debhelper.in/libc.preinst index 1a6d5aa..ac3626d 100644 --- a/debian/debhelper.in/libc.preinst +++ b/debian/debhelper.in/libc.preinst @@ -118,6 +118,27 @@ check_dir () { done } +remove_lib64_symlink() { + ldfile=$(readlink -e RTLD_SO) + # Test if libc is of the same architecture as coreutils + # If not, they almost surely have a multiarch system and we can use + # the native ELF interpreter + if ! $ldfile /bin/true 2>/dev/null; then + interpreter= + else + interpreter=$ldfile + fi + + # sync before and after the operation to reduce the danger of hosing + # the system + sync + rm -f /lib64 + $interpreter /bin/mkdir /lib64 + $interpreter /bin/ln -s $ldfile RTLD_SO + sync +} + + if [ "$type" = upgrade ] then # Remove old /etc/init.d/glibc.sh init script @@ -383,6 +404,15 @@ fi #DEBHELPER# +if [ "$type" = upgrade ]; then + if test -L /lib64; then + case ${DPKG_MAINTSCRIPT_ARCH:-$(dpkg --print-architecture)} in + amd64 | ppc64 | sparc64 | s390x) + remove_lib64_symlink ;; + esac + fi +fi + if [ -n "$preversion" ]; then if dpkg --compare-versions "$preversion" lt 2.13-5; then # upgrading from a pre-multiarch libc to a multiarch libc; we have -- 1.7.5.4
>From 50874b20a65cb91dd4430c75d981503ec17ed49c Mon Sep 17 00:00:00 2001 From: Sven Joachim <svenj...@gmx.de> Date: Thu, 11 Aug 2011 22:36:52 +0200 Subject: [PATCH 4/6] Restore multiarch support on all architectures --- debian/rules.d/debhelper.mk | 14 +------------- 1 files changed, 1 insertions(+), 13 deletions(-) diff --git a/debian/rules.d/debhelper.mk b/debian/rules.d/debhelper.mk index 1f21083..4d6d07d 100644 --- a/debian/rules.d/debhelper.mk +++ b/debian/rules.d/debhelper.mk @@ -109,19 +109,7 @@ endif dh_installdeb -p$(curpass) dh_shlibdeps -p$(curpass) - - # - # Disable multiarch support on some architectures until we fix the /lib64 -> /lib issue - # - case $(curpass)/$(DEB_HOST_ARCH) in \ - libc6/amd64 | libc0.1/kfreebsd-amd64 | libc6/ppc64 | libc6/s390x | libc6/sparc64) \ - dh_gencontrol -p$(curpass) -- -UMulti-Arch \ - ;; \ - *) \ - dh_gencontrol -p$(curpass) \ - ;; \ - esac - + dh_gencontrol -p$(curpass) if [ $(curpass) = nscd ] ; then \ sed -i -e "s/\(Depends:.*libc[0-9.]\+\)-[a-z0-9]\+/\1/" debian/nscd/DEBIAN/control ; \ fi -- 1.7.5.4
>From 12513329363e28b2723bc646deaadebace12d7ce Mon Sep 17 00:00:00 2001 From: Sven Joachim <svenj...@gmx.de> Date: Sat, 13 Aug 2011 17:36:14 +0200 Subject: [PATCH 5/6] Restore the /lib64 symlink on downgrades It might be more prudent to prevent the downgrade from happening, but if we fail the prerm script, the one from the previous version kicks in and succeeds, unless the dpkg version doing the downgrade is 1.16.1 or later (not released yet). After that there is no way to stop the machinery which leads to the loss of the dynamic linker. --- debian/debhelper.in/libc.prerm | 46 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+), 0 deletions(-) diff --git a/debian/debhelper.in/libc.prerm b/debian/debhelper.in/libc.prerm index 6f1a7db..33e7a54 100644 --- a/debian/debhelper.in/libc.prerm +++ b/debian/debhelper.in/libc.prerm @@ -7,8 +7,54 @@ if [ "x$2" != "xin-favour" ]; then preversion=$2 fi +restore_lib64_symlink() { +# Downgrading from a version with a /lib64 directory to a version with +# a /lib64 symlink is extremely dangerous. We need to move the +# directory aside and restore the symlink, otherwise the dynamic +# linker gets lost after unpacking the replacing version. + + ldfile=$(readlink -e RTLD_SO) + # Test if libc is of the same architecture as coreutils + # If not, they almost surely have a multiarch system and we can use + # the native ELF interpreter + if ! $ldfile /bin/true 2>/dev/null; then + interpreter= + else + interpreter=$ldfile + fi + + # sync before and after the operation to reduce the danger of hosing + # the system + sync + # See if they have anything in /lib64 besides the ELF interpreter. + # If yes, move the directory aside so they can restore it later, + # otherwise we just remove it. + if ls -A /lib64 | grep -vq "^$(basename RTLD_SO)$"; then + aside=$(mktemp -u /lib64-renamed-by-libc6-prerm.XXXXXX) + echo "Warning: /lib64 not empty during libc downgrade, renaming it to $aside" + mv /lib64 $aside + else + rm -rf /lib64 + fi + + $interpreter /bin/ln -s /lib /lib64 + sync +} + + #DEBHELPER# +if [ "$type" = upgrade ]; then + if dpkg --compare-versions "$preversion" lt 2.13-17; then + if ! test -L /lib64; then + case ${DPKG_MAINTSCRIPT_ARCH:-$(dpkg --print-architecture)} in + amd64 | ppc64 | sparc64 | s390x) + restore_lib64_symlink ;; + esac + fi + fi +fi + if [ -n "$preversion" ]; then if dpkg --compare-versions "$preversion" lt 2.13-5; then # downgrading from a multiarch libc to a pre-multiarch libc; we have -- 1.7.5.4
>From 311f8d95c8d9ee2675bd57fd12ac49caa99d4404 Mon Sep 17 00:00:00 2001 From: Sven Joachim <svenj...@gmx.de> Date: Mon, 15 Aug 2011 16:02:29 +0200 Subject: [PATCH 6/6] Check for free inode before /lib64 symlink conversion On a system that does not have any free inodes creating the RTLD_SO symlink in preinst respectively the /lib64 symlink in the prerm on downgrades will fail and hose the system. The check introduced here is not perfect due to race conditions, but better than nothing. --- debian/debhelper.in/libc.preinst | 4 ++++ debian/debhelper.in/libc.prerm | 6 +++++- 2 files changed, 9 insertions(+), 1 deletions(-) diff --git a/debian/debhelper.in/libc.preinst b/debian/debhelper.in/libc.preinst index ac3626d..f391bf6 100644 --- a/debian/debhelper.in/libc.preinst +++ b/debian/debhelper.in/libc.preinst @@ -132,6 +132,10 @@ remove_lib64_symlink() { # sync before and after the operation to reduce the danger of hosing # the system sync + # Removing the /lib64 symlink frees one inode while creating it as + # a directory and the symlink in it takes two. Check if there is + # at least one free inode available. + rm $(mktemp /need-a-free-inode.XXXXXX) rm -f /lib64 $interpreter /bin/mkdir /lib64 $interpreter /bin/ln -s $ldfile RTLD_SO diff --git a/debian/debhelper.in/libc.prerm b/debian/debhelper.in/libc.prerm index 33e7a54..b69b728 100644 --- a/debian/debhelper.in/libc.prerm +++ b/debian/debhelper.in/libc.prerm @@ -30,7 +30,11 @@ restore_lib64_symlink() { # If yes, move the directory aside so they can restore it later, # otherwise we just remove it. if ls -A /lib64 | grep -vq "^$(basename RTLD_SO)$"; then - aside=$(mktemp -u /lib64-renamed-by-libc6-prerm.XXXXXX) + # We don't use mktemp -u here so that we can test if there is + # at least one free inode. That one is needed to create the + # /lib64 symlink later. + aside=$(mktemp /lib64-renamed-by-libc6-prerm.XXXXXX) + rm $aside echo "Warning: /lib64 not empty during libc downgrade, renaming it to $aside" mv /lib64 $aside else -- 1.7.5.4