Tar extracting on root directory is destroying entire system

bashlinuxpermissionstarunix

I'm not sure whats going on… I wasn't aware tar did this. But when I extract a tar on top of the root fs (/) with all the permission stuff turned off… for instance:

root@system:~# tar --no-same-owner --no-same-permissions --no-overwrite-dir -C / -xzvf test.tar.gz 
./
./lib/
./lib/test
...

This precedes to destroy everything in /usr/bin (I think)… diagnosed by the most troubling error ever:

root@system:~# ls
-bash: /usr/bin/ls: No such file or directory

The whole OS is pretty much FUBR at this point… I don't understand what's happening.

Best Answer

Many newer Linux distributions (like Fedora for a long time or Debian very recently) switched to using symlinks to /usr for some base directories. The rationale for this switch is explained there.

Among the directories replaced with symlinks are:

/
├── bin -> usr/bin
├── lib -> usr/lib
├── lib32 -> usr/lib32
├── lib64 -> usr/lib64
├── libx32 -> usr/libx32
├── sbin -> usr/sbin

Dearchiving a tar archive made from a build system or an install staging area not adhering to the same conventions and that includes not only a file but the directory including this file, will delete the symlink (--no-overwrite-dir didn't see a directory but a symlink) having the same name as the directory and write the new directory with its scarce content instead.

So there is a difference when creating the archive of a directory and the archive of the contents of a directory:

tar -cf test.tar.gz lib

and:

tar -cf test.tar.gz lib/*

the later won't have a directory in the archive, so won't erase the original symlink when being extracted.

If the former is extracted on a live system, default library path likely won't be able to find libraries in the expected place anymore.

A fix for this on a system where a root shell is still currently available would look like this (on amd64 / x86_64 arch for this example):

/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 --library-path /usr/lib/x86_64-linux-gnu /usr/bin/mv /lib /lib_moved
/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 --library-path /usr/lib/x86_64-linux-gnu /usr/bin/ln -s usr/lib /lib

and if needed other similar fixes for other deleted symlinks.

Related Question