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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user