diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-24 17:20:13 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-24 17:20:13 +0200 |
commit | b920a38dc0a87f5884444d4731a8b887b5e16018 (patch) | |
tree | 5d845976a9471e705183db9afbbe7885e9070b52 /archival/libarchive/data_extract_all.c | |
parent | c810978552bc0133ba723ababaa178c8d53256e1 (diff) |
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>
Diffstat (limited to 'archival/libarchive/data_extract_all.c')
-rw-r--r-- | archival/libarchive/data_extract_all.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 1830ffb8d..1ce927c2f 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c @@ -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: |