upgrade of libc-2.3.3.so to libc-2.3.6.so problematic?

Brandon Peirce brandon_peirce at hotmail.com
Sun Aug 27 19:50:42 PDT 2006


Dan Nicholson wrote:
>So, you want to install into a temporary location.
>
>make install_root=/some/temp/location install

Certainly, however you proceed after to upgrade your live system
you want to start with the above.  You don't want to leave this
critical installation in the hands of the Makefile!

>I stole this from Greg Shafer's scripts, and David Rosal, who wrote
>the paco package manager, has dubbed it the "tar sandwich". As root:
>
>cd /some/temp/location
>tar -cf - . | tar -C / -xf -

>For
>reasons that I can't explain fully, this is safer than "rm
>/lib/libc.so.x.y.z && install -m755 libc.so.x.y.z /lib" which is
>basically what the Makefile would do.

That may be so, but you want to be very careful about the way tar
(mis)handles overwriting of existing symlinks.  If Dan says he's done
it exactly like that, then I must believe him.  But I suspect you might
not get exactly the result you expect.... The tar sandwich is good but
I would suggest to exclude the symlinks in /some/temp/location
from that sandwich.

Let's take a look what's going on.  Almost every binary on your system
needs at least 2 critical files just to be able to start.  Take any basic
binary that you think you might need during the upgrade: rm, mv, cp,
ln, tar,... and examine it:

bash$ ldd /bin/cp
        libc.so.6 => /lib/libc.so.6 (0xb7eb9000)
        /lib/ld-linux.so.2 (0xb7feb000)

So, I think you can appreciate that if you mess up either of these 2
files, you will no longer be able to start any of the commands that you
need to fix the mess and you are hosed.  Time to dive for the boot-CD.
(Well actually there's another life-saver I will come back to.)

Take a look and you will see that both these critical files are actually
symlinks:
/lib/libc.so.6 -> libc-2.3.3.so
/lib/ld-linux.so.2 -> ld-2.3.3.so

So the basic approach, which I have used successfully, is to install the
new files /lib/libc-2.3.6.so and /lib/ld-2.3.6.so then adjust the symlinks
to point to the new files.  Remember that if you do something like
(cd /lib; rm -f libc.so.6; ln -s libc-2.3.6.so libc.so.6) you will be 
screwed
because the ln -s will be unable to start due to the missing libc.so.
Normally something like (cd /lib; ln -sf libc-2.3.6.so libc.so.6) is fine
but you definitely want to know about sln before you attempt this.

Of course, you don't want to do that 'by hand' for each file, but it helps
to understand what's going on in case you have to recover by hand.
The basic steps are
1. configure and compile glibc and install to /some/temp/location
2. check /some/temp/location and remove any files you do not want to
overwrite, e.g. customized versions of etc/ld.so.conf or
etc/nsswitch.conf
3. remove the symlinks from /some/temp/location and create a suitable
script (see below).
4. do your backups, and make sure you also have a backup copy of
sln binary on your root partition.  It comes with glibc so it will be
overwritten and something could go wrong...
5. do the tar sandwitch thingy to install the new files including the new
shared libraries.  this shouldn't break anything critical yet 'cos the
the 2.3.3 files and symlinks pointing to them are still in place.
6. run the script created in step 3 to upgrade the symlinks.
7. now you should be running with the new glibc.  check that stuff still
works.
8. you may want to reboot now as Dan suggested, but don't do it before
you have verified that things work. If you have a libc problem, then things
like mount will not work when you reboot and your init scripts will fail
horribly.
9. if all is good, remove the old 2.3.3 files (only files not common
between the versions, i.e. only the ones containing version num in the
file name).

For the script mentioned in steps 3 & 6, you can use code similar to the
following (heavily based on ideas from Slackware's pkgtool scripts):

cd /some/temp/location
find . -type l \
	| xargs ls -l --time-style=long-iso \
	| sed -e 's/ \+/ /g' \
	| cut -d ' ' -f 8,10  \
	| while read link link_trgt && [ -n "$link" ]
do
	link_name=`basename $link`
	link_dir=`dirname $link`
	echo "( cd $link_dir" \
	     "; sln $link_trgt $link_name )" >>/some/script/file
	rm -f $link
done

(The sed is to squeeze double spaces between some
columns of ls output for the benefit of cut.)
This will delete all the symlinks from the temp location and create a
script that looks like
...
(cd /lib; sln libc-2.3.6.so libc.so.6)
(cd /lib; sln ld-2.3.3.so ld-linux.so.2)
...

Warning: You are about to attempt a potentially catastrophic upgrade.
Don't take my word for it.  Test the above code in /another/temp/dir
and be sure it does what you want.  Familiarize yourself with sln. It
does not support all the syntax variations and options of the
core-utils ln, and the behaviour is different in some cases, particularly
overwriting existing links. IIRC sln behaves more like ln -s -f


>Good luck. I'd make sure to make a backup of the original glibc and
>make sure I had a LiveCD handy in case anything terrible happened.

Definitely follow that good advice.  Remember that if libc is bust the
only tools you have (unless you boot live CD) are:
1. static binaries like sln
2. shell builtins (so don't exit your only running shell instance!)
- subshells work if needed with constructs like (...) `...` or pipelines.
- cd is a shell builtin
- echo *  can be used as a crude substitute for ls
- it's painful but you can crudely emulate cat with a construct like
while read LINE </some/file; do echo "$LINE"; done

That's about it.  I too wish you good luck :)

Brandon





More information about the lfs-support mailing list