Bug 1519 - hardlink of symlink in archive messes up permissions
Summary: hardlink of symlink in archive messes up permissions
Status: RESOLVED FIXED
Alias: None
Product: Busybox
Classification: Unclassified
Component: Other (show other bugs)
Version: 1.16.x
Hardware: PC Linux
: P5 minor
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-04-08 11:52 UTC by Nils Rennebarth
Modified: 2010-04-17 06:09 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nils Rennebarth 2010-04-08 11:52:57 UTC
If an archive contains a hardlink of a symlink, extracting the hardlink messes
up the permissions of the real file.
Assume the following situtation (under linux, other OS may behave differently,
but I heard Solaris does the same)

$ touch file
$ ln -s file link
$ mkdir dir
$ ln file dir
$ ln link dir

Now dir will contain two hardlinks, one named "file" and one named "link"
When GNU tar creates an archive of all this and busybox tar extracts it,
the "file" will have permission 777.

The bug lies in archival/libunarchive/data_extract_all.c, where hardlinks
are first handled separately (line 73-80), but later chown and chmod is
performed, and that is done by chmod itself, which uses the
permissions of the symlink which are always 777.

I would argue that a hardlink has no permissions (nor timestamps nor
uid/gid) itself, because all that data is in the inode. And the code
relies on the existance of the link target already, so my proposal
for a fix would be to simply return on line 80.
Comment 1 Denys Vlasenko 2010-04-09 08:53:24 UTC
Works for me:


tar.tests:
==========
#!/bin/sh
rm -rf input_* test.tar 2>/dev/null

>input_hard1
chmod 741 input_hard1
ln input_hard1 input_hard2
mkdir input_dir
chmod 550 input_dir
ln input_hard1 input_dir
ln input_hard2 input_dir

/usr/bin/tar cf test.tar input_*
rm -rf input_*

./busybox tar tvf test.tar
./busybox tar xf test.tar
echo Ok: $?
ls -l . input_dir/* | grep input_
rm -rf input_* test.tar 2>/dev/null


Running it:


dr-xr-x--- root/root  0 2010-04-09 10:50:08 input_dir/
-rwxr----x root/root  0 2010-04-09 10:50:08 input_dir/input_hard1
-rwxr----x root/root  0 2010-04-09 10:50:08 input_dir/input_hard2 -> input_dir/input_hard1
-rwxr----x root/root  0 2010-04-09 10:50:08 input_hard1 -> input_dir/input_hard1
-rwxr----x root/root  0 2010-04-09 10:50:08 input_hard2 -> input_dir/input_hard1
Ok: 0
-rwxr----x    4 root     root             0 Apr  9 10:50 input_dir/input_hard1
-rwxr----x    4 root     root             0 Apr  9 10:50 input_dir/input_hard2
dr-xr-x---    2 root     root           112 Apr  9 10:50 input_dir
-rwxr----x    4 root     root             0 Apr  9 10:50 input_hard1
-rwxr----x    4 root     root             0 Apr  9 10:50 input_hard2
Comment 2 Denys Vlasenko 2010-04-09 11:43:32 UTC
Ahh... I see! It happens with hardlink TO SYMLINK
Comment 3 Denys Vlasenko 2010-04-09 12:12:39 UTC
Fixed in git, please test.