tar: postpone creation of symlinks with "suspicious" targets. Closes 8411

function                                             old     new   delta
data_extract_all                                     968    1038     +70
tar_main                                             952     986     +34
scan_tree                                            258     262      +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 108/0)             Total: 108 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko
2017-07-24 17:20:13 +02:00
parent c810978552
commit b920a38dc0
6 changed files with 130 additions and 36 deletions

View File

@@ -128,10 +128,11 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
res = link(hard_link, dst_name);
if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
/* shared message */
bb_perror_msg("can't create %slink "
"%s to %s", "hard",
bb_perror_msg("can't create %slink '%s' to '%s'",
"hard",
dst_name,
hard_link);
hard_link
);
}
/* Hardlinks have no separate mode/ownership, skip chown/chmod */
goto ret;
@@ -178,15 +179,44 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
case S_IFLNK:
/* Symlink */
//TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
/* To avoid a directory traversal attack via symlinks,
* for certain link targets postpone creation of symlinks.
*
* For example, consider a .tar created via:
* $ tar cvf bug.tar anything.txt
* $ ln -s /tmp symlink
* $ tar --append -f bug.tar symlink
* $ rm symlink
* $ mkdir symlink
* $ tar --append -f bug.tar symlink/evil.py
*
* This will result in an archive that contains:
* $ tar --list -f bug.tar
* anything.txt
* symlink [-> /tmp]
* symlink/evil.py
*
* Untarring bug.tar would otherwise place evil.py in '/tmp'.
*/
if (file_header->link_target[0] == '/'
|| strstr(file_header->link_target, "..")
) {
llist_add_to(&archive_handle->symlink_placeholders,
xasprintf("%s%c%s", file_header->name, '\0', file_header->link_target)
);
break;
}
res = symlink(file_header->link_target, dst_name);
if (res != 0
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
) {
/* shared message */
bb_perror_msg("can't create %slink "
"%s to %s", "sym",
bb_perror_msg("can't create %slink '%s' to '%s'",
"sym",
dst_name,
file_header->link_target);
file_header->link_target
);
}
break;
case S_IFSOCK: