aboutsummaryrefslogtreecommitdiff
path: root/archival/libarchive
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-02-20 15:57:45 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-02-20 16:06:53 +0100
commita84db18fc71d09e801df0ebca048d82e90b32c6a (patch)
tree1eda8cd659f78406f1b9f86d5e0b5757af20bad9 /archival/libarchive
parent95121d98e6da12599246d8e25c3f300e422a06fb (diff)
downloadbusybox-w32-a84db18fc71d09e801df0ebca048d82e90b32c6a.tar.gz
busybox-w32-a84db18fc71d09e801df0ebca048d82e90b32c6a.tar.bz2
busybox-w32-a84db18fc71d09e801df0ebca048d82e90b32c6a.zip
tar,unzip: postpone creation of symlinks with "suspicious" targets
This mostly reverts commit bc9bbeb2b81001e8731cd2ae501c8fccc8d87cc7 "libarchive: do not extract unsafe symlinks unless $EXTRACT_UNSAFE_SYMLINKS=1" Users report that it is somewhat too restrictive. See https://bugs.busybox.net/show_bug.cgi?id=8411 In particular, this interferes with unpacking of busybox-based filesystems with links like "sbin/applet" -> "../bin/busybox". The change is made smaller by deleting ARCHIVE_EXTRACT_QUIET flag - it is unused since 2010, and removing conditionals on it allows commonalizing some error message codes. function old new delta create_or_remember_symlink - 94 +94 create_symlinks_from_list - 64 +64 tar_main 1002 1006 +4 unzip_main 2732 2724 -8 data_extract_all 984 891 -93 unsafe_symlink_target 147 - -147 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 1/2 up/down: 162/-248) Total: -86 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'archival/libarchive')
-rw-r--r--archival/libarchive/data_extract_all.c28
-rw-r--r--archival/libarchive/unsafe_symlink_target.c59
2 files changed, 33 insertions, 54 deletions
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index d3a6df5e8..8fa69ffaf 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -107,9 +107,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
107 } 107 }
108 } 108 }
109 else if (existing_sb.st_mtime >= file_header->mtime) { 109 else if (existing_sb.st_mtime >= file_header->mtime) {
110 if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 110 if (!S_ISDIR(file_header->mode)) {
111 && !S_ISDIR(file_header->mode)
112 ) {
113 bb_error_msg("%s not created: newer or " 111 bb_error_msg("%s not created: newer or "
114 "same age file exists", dst_name); 112 "same age file exists", dst_name);
115 } 113 }
@@ -125,7 +123,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
125 /* Handle hard links separately */ 123 /* Handle hard links separately */
126 if (hard_link) { 124 if (hard_link) {
127 res = link(hard_link, dst_name); 125 res = link(hard_link, dst_name);
128 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { 126 if (res != 0) {
129 /* shared message */ 127 /* shared message */
130 bb_perror_msg("can't create %slink '%s' to '%s'", 128 bb_perror_msg("can't create %slink '%s' to '%s'",
131 "hard", dst_name, hard_link 129 "hard", dst_name, hard_link
@@ -165,10 +163,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
165 } 163 }
166 case S_IFDIR: 164 case S_IFDIR:
167 res = mkdir(dst_name, file_header->mode); 165 res = mkdir(dst_name, file_header->mode);
168 if ((res == -1) 166 if ((res != 0)
169 && (errno != EISDIR) /* btw, Linux doesn't return this */ 167 && (errno != EISDIR) /* btw, Linux doesn't return this */
170 && (errno != EEXIST) 168 && (errno != EEXIST)
171 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
172 ) { 169 ) {
173 bb_perror_msg("can't make dir %s", dst_name); 170 bb_perror_msg("can't make dir %s", dst_name);
174 } 171 }
@@ -198,27 +195,16 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
198 * 195 *
199 * Untarring bug.tar would otherwise place evil.py in '/tmp'. 196 * Untarring bug.tar would otherwise place evil.py in '/tmp'.
200 */ 197 */
201 if (!unsafe_symlink_target(file_header->link_target)) { 198 create_or_remember_symlink(&archive_handle->symlink_placeholders,
202 res = symlink(file_header->link_target, dst_name); 199 file_header->link_target,
203 if (res != 0 200 dst_name);
204 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
205 ) {
206 /* shared message */
207 bb_perror_msg("can't create %slink '%s' to '%s'",
208 "sym",
209 dst_name, file_header->link_target
210 );
211 }
212 }
213 break; 201 break;
214 case S_IFSOCK: 202 case S_IFSOCK:
215 case S_IFBLK: 203 case S_IFBLK:
216 case S_IFCHR: 204 case S_IFCHR:
217 case S_IFIFO: 205 case S_IFIFO:
218 res = mknod(dst_name, file_header->mode, file_header->device); 206 res = mknod(dst_name, file_header->mode, file_header->device);
219 if ((res == -1) 207 if (res != 0) {
220 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
221 ) {
222 bb_perror_msg("can't create node %s", dst_name); 208 bb_perror_msg("can't create node %s", dst_name);
223 } 209 }
224 break; 210 break;
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
index 441ba8b24..8dcafeaa1 100644
--- a/archival/libarchive/unsafe_symlink_target.c
+++ b/archival/libarchive/unsafe_symlink_target.c
@@ -5,44 +5,37 @@
5#include "libbb.h" 5#include "libbb.h"
6#include "bb_archive.h" 6#include "bb_archive.h"
7 7
8int FAST_FUNC unsafe_symlink_target(const char *target) 8void FAST_FUNC create_or_remember_symlink(llist_t **symlink_placeholders,
9 const char *target,
10 const char *linkname)
9{ 11{
10 const char *dot; 12 if (target[0] == '/' || strstr(target, "..")) {
11 13 llist_add_to(symlink_placeholders,
12 if (target[0] == '/') { 14 xasprintf("%s%c%s", linkname, '\0', target)
13 const char *var; 15 );
14 unsafe: 16 return;
15 var = getenv("EXTRACT_UNSAFE_SYMLINKS"); 17 }
16 if (var) { 18 if (symlink(target, linkname) != 0) {
17 if (LONE_CHAR(var, '1')) 19 /* shared message */
18 return 0; /* pretend it's safe */ 20 bb_perror_msg_and_die("can't create %slink '%s' to '%s'",
19 return 1; /* "UNSAFE!" */ 21 "sym", linkname, target
20 }
21 bb_error_msg("skipping unsafe symlink to '%s' in archive,"
22 " set %s=1 to extract",
23 target,
24 "EXTRACT_UNSAFE_SYMLINKS"
25 ); 22 );
26 /* Prevent further messages */
27 setenv("EXTRACT_UNSAFE_SYMLINKS", "0", 0);
28 return 1; /* "UNSAFE!" */
29 } 23 }
24}
30 25
31 dot = target; 26void FAST_FUNC create_symlinks_from_list(llist_t *list)
32 for (;;) { 27{
33 dot = strchr(dot, '.'); 28 while (list) {
34 if (!dot) 29 char *target;
35 return 0; /* safe target */
36 30
37 /* Is it a path component starting with ".."? */ 31 target = list->data + strlen(list->data) + 1;
38 if ((dot[1] == '.') 32 if (symlink(target, list->data)) {
39 && (dot == target || dot[-1] == '/') 33 /* shared message */
40 /* Is it exactly ".."? */ 34 bb_error_msg_and_die("can't create %slink '%s' to '%s'",
41 && (dot[2] == '/' || dot[2] == '\0') 35 "sym",
42 ) { 36 list->data, target
43 goto unsafe; 37 );
44 } 38 }
45 /* NB: it can even be trailing ".", should only add 1 */ 39 list = list->link;
46 dot += 1;
47 } 40 }
48} 41}