diff options
author | Ron Yorston <rmy@pobox.com> | 2017-08-22 14:56:12 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2017-08-22 14:56:12 +0100 |
commit | ce9af1cc5ea23f754587448cf35b5120c77bfeef (patch) | |
tree | 69e5eaba5e75ab909ed92d5045393471b8ff3c13 /archival/libarchive | |
parent | c170026700eabb10147dd848c45c06995b43a32e (diff) | |
parent | e837a0dbbebf4229306df98fe9ee3b9bb30630c4 (diff) | |
download | busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.tar.gz busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.tar.bz2 busybox-w32-ce9af1cc5ea23f754587448cf35b5120c77bfeef.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'archival/libarchive')
-rw-r--r-- | archival/libarchive/Kbuild.src | 2 | ||||
-rw-r--r-- | archival/libarchive/data_extract_all.c | 37 | ||||
-rw-r--r-- | archival/libarchive/decompress_unxz.c | 1 | ||||
-rw-r--r-- | archival/libarchive/open_transformer.c | 40 | ||||
-rw-r--r-- | archival/libarchive/unsafe_symlink_target.c | 48 |
5 files changed, 93 insertions, 35 deletions
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 942e755b9..e1a8a7529 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src | |||
@@ -12,6 +12,8 @@ COMMON_FILES:= \ | |||
12 | data_extract_all.o \ | 12 | data_extract_all.o \ |
13 | data_extract_to_stdout.o \ | 13 | data_extract_to_stdout.o \ |
14 | \ | 14 | \ |
15 | unsafe_symlink_target.o \ | ||
16 | \ | ||
15 | filter_accept_all.o \ | 17 | filter_accept_all.o \ |
16 | filter_accept_list.o \ | 18 | filter_accept_list.o \ |
17 | filter_accept_reject_list.o \ | 19 | filter_accept_reject_list.o \ |
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 1ce927c2f..e658444e0 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
@@ -129,9 +129,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
129 | if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { | 129 | if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
130 | /* shared message */ | 130 | /* shared message */ |
131 | bb_perror_msg("can't create %slink '%s' to '%s'", | 131 | bb_perror_msg("can't create %slink '%s' to '%s'", |
132 | "hard", | 132 | "hard", dst_name, hard_link |
133 | dst_name, | ||
134 | hard_link | ||
135 | ); | 133 | ); |
136 | } | 134 | } |
137 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ | 135 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ |
@@ -181,7 +179,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
181 | //TODO: what if file_header->link_target == NULL (say, corrupted tarball?) | 179 | //TODO: what if file_header->link_target == NULL (say, corrupted tarball?) |
182 | 180 | ||
183 | /* To avoid a directory traversal attack via symlinks, | 181 | /* To avoid a directory traversal attack via symlinks, |
184 | * for certain link targets postpone creation of symlinks. | 182 | * do not restore symlinks with ".." components |
183 | * or symlinks starting with "/", unless a magic | ||
184 | * envvar is set. | ||
185 | * | 185 | * |
186 | * For example, consider a .tar created via: | 186 | * For example, consider a .tar created via: |
187 | * $ tar cvf bug.tar anything.txt | 187 | * $ tar cvf bug.tar anything.txt |
@@ -199,24 +199,17 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
199 | * | 199 | * |
200 | * Untarring bug.tar would otherwise place evil.py in '/tmp'. | 200 | * Untarring bug.tar would otherwise place evil.py in '/tmp'. |
201 | */ | 201 | */ |
202 | if (file_header->link_target[0] == '/' | 202 | if (!unsafe_symlink_target(file_header->link_target)) { |
203 | || strstr(file_header->link_target, "..") | 203 | res = symlink(file_header->link_target, dst_name); |
204 | ) { | 204 | if (res != 0 |
205 | llist_add_to(&archive_handle->symlink_placeholders, | 205 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
206 | xasprintf("%s%c%s", file_header->name, '\0', file_header->link_target) | 206 | ) { |
207 | ); | 207 | /* shared message */ |
208 | break; | 208 | bb_perror_msg("can't create %slink '%s' to '%s'", |
209 | } | 209 | "sym", |
210 | res = symlink(file_header->link_target, dst_name); | 210 | dst_name, file_header->link_target |
211 | if (res != 0 | 211 | ); |
212 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | 212 | } |
213 | ) { | ||
214 | /* shared message */ | ||
215 | bb_perror_msg("can't create %slink '%s' to '%s'", | ||
216 | "sym", | ||
217 | dst_name, | ||
218 | file_header->link_target | ||
219 | ); | ||
220 | } | 213 | } |
221 | break; | 214 | break; |
222 | case S_IFSOCK: | 215 | case S_IFSOCK: |
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 350e5358a..0be85500c 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c | |||
@@ -37,7 +37,6 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) | |||
37 | || !defined(put_unaligned_be32) | 37 | || !defined(put_unaligned_be32) |
38 | # error get_unaligned_le32 accessors are not defined | 38 | # error get_unaligned_le32 accessors are not defined |
39 | #endif | 39 | #endif |
40 | #define get_le32(p) (*(uint32_t*)(p)) | ||
41 | 40 | ||
42 | #include "unxz/xz_dec_bcj.c" | 41 | #include "unxz/xz_dec_bcj.c" |
43 | #include "unxz/xz_dec_lzma2.c" | 42 | #include "unxz/xz_dec_lzma2.c" |
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 641256787..7d912152c 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -251,18 +251,8 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp | |||
251 | return xstate; | 251 | return xstate; |
252 | } | 252 | } |
253 | 253 | ||
254 | /* Used by e.g. rpm which gives us a fd without filename, | 254 | static void fork_transformer_and_free(transformer_state_t *xstate) |
255 | * thus we can't guess the format from filename's extension. | ||
256 | */ | ||
257 | int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | ||
258 | { | 255 | { |
259 | transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); | ||
260 | |||
261 | if (!xstate || !xstate->xformer) { | ||
262 | free(xstate); | ||
263 | return 1; | ||
264 | } | ||
265 | |||
266 | # if BB_MMU | 256 | # if BB_MMU |
267 | fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); | 257 | fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); |
268 | # else | 258 | # else |
@@ -270,13 +260,39 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | |||
270 | * an external unzipper that wants | 260 | * an external unzipper that wants |
271 | * file position at the start of the file. | 261 | * file position at the start of the file. |
272 | */ | 262 | */ |
273 | xlseek(fd, - xstate->signature_skipped, SEEK_CUR); | 263 | xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR); |
274 | xstate->signature_skipped = 0; | 264 | xstate->signature_skipped = 0; |
275 | fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); | 265 | fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); |
276 | # endif | 266 | # endif |
277 | free(xstate); | 267 | free(xstate); |
268 | } | ||
269 | |||
270 | /* Used by e.g. rpm which gives us a fd without filename, | ||
271 | * thus we can't guess the format from filename's extension. | ||
272 | */ | ||
273 | int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) | ||
274 | { | ||
275 | transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); | ||
276 | |||
277 | if (!xstate->xformer) { | ||
278 | free(xstate); | ||
279 | return 1; | ||
280 | } | ||
281 | |||
282 | fork_transformer_and_free(xstate); | ||
278 | return 0; | 283 | return 0; |
279 | } | 284 | } |
285 | #if ENABLE_FEATURE_SEAMLESS_LZMA | ||
286 | /* ...and custom version for LZMA */ | ||
287 | void FAST_FUNC setup_lzma_on_fd(int fd) | ||
288 | { | ||
289 | transformer_state_t *xstate = xzalloc(sizeof(*xstate)); | ||
290 | xstate->src_fd = fd; | ||
291 | xstate->xformer = unpack_lzma_stream; | ||
292 | USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";) | ||
293 | fork_transformer_and_free(xstate); | ||
294 | } | ||
295 | #endif | ||
280 | 296 | ||
281 | static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) | 297 | static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) |
282 | { | 298 | { |
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c new file mode 100644 index 000000000..441ba8b24 --- /dev/null +++ b/archival/libarchive/unsafe_symlink_target.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
4 | */ | ||
5 | #include "libbb.h" | ||
6 | #include "bb_archive.h" | ||
7 | |||
8 | int FAST_FUNC unsafe_symlink_target(const char *target) | ||
9 | { | ||
10 | const char *dot; | ||
11 | |||
12 | if (target[0] == '/') { | ||
13 | const char *var; | ||
14 | unsafe: | ||
15 | var = getenv("EXTRACT_UNSAFE_SYMLINKS"); | ||
16 | if (var) { | ||
17 | if (LONE_CHAR(var, '1')) | ||
18 | return 0; /* pretend it's safe */ | ||
19 | return 1; /* "UNSAFE!" */ | ||
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 | ); | ||
26 | /* Prevent further messages */ | ||
27 | setenv("EXTRACT_UNSAFE_SYMLINKS", "0", 0); | ||
28 | return 1; /* "UNSAFE!" */ | ||
29 | } | ||
30 | |||
31 | dot = target; | ||
32 | for (;;) { | ||
33 | dot = strchr(dot, '.'); | ||
34 | if (!dot) | ||
35 | return 0; /* safe target */ | ||
36 | |||
37 | /* Is it a path component starting with ".."? */ | ||
38 | if ((dot[1] == '.') | ||
39 | && (dot == target || dot[-1] == '/') | ||
40 | /* Is it exactly ".."? */ | ||
41 | && (dot[2] == '/' || dot[2] == '\0') | ||
42 | ) { | ||
43 | goto unsafe; | ||
44 | } | ||
45 | /* NB: it can even be trailing ".", should only add 1 */ | ||
46 | dot += 1; | ||
47 | } | ||
48 | } | ||