[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#632682: base-files: please provide a /lib64 -> /lib symlink on 64-bit systems



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 <svenjoac@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 <svenjoac@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 <svenjoac@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 <svenjoac@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 <svenjoac@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 <svenjoac@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


Reply to: