diff options
Diffstat (limited to 'archival/tar.c')
-rw-r--r-- | archival/tar.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/archival/tar.c b/archival/tar.c index 0fc574d..280ded4 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -22,24 +22,6 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -/* TODO: security with -C DESTDIR option can be enhanced. - * Consider tar file 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 which contains: - * $ tar --list -f bug.tar - * anything.txt - * symlink - * symlink/evil.py - * - * Untarring it puts evil.py in '/tmp' even if the -C DESTDIR is given. - * This doesn't feel right, and IIRC GNU tar doesn't do that. - */ //config:config TAR //config: bool "tar (40 kb)" @@ -296,6 +278,23 @@ static void chksum_and_xwrite(int fd, struct tar_header_t* hp) xwrite(fd, hp, sizeof(*hp)); } +static void replace_symlink_placeholders(llist_t *list) +{ + while (list) { + char *target; + + target = list->data + strlen(list->data) + 1; + if (symlink(target, list->data)) { + /* shared message */ + bb_error_msg_and_die("can't create %slink '%s' to '%s'", + "sym", + list->data, target + ); + } + list = list->link; + } +} + #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS static void writeLongname(int fd, int type, const char *name, int dir) { @@ -1252,6 +1251,8 @@ int tar_main(int argc UNUSED_PARAM, char **argv) while (get_header_tar(tar_handle) == EXIT_SUCCESS) bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */ + replace_symlink_placeholders(tar_handle->symlink_placeholders); + /* Check that every file that should have been extracted was */ while (tar_handle->accept) { if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) |