diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-11 19:28:39 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-11 19:28:39 +0200 |
commit | 6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467 (patch) | |
tree | 1961565061f829aabe0664af7ef076909e6ded72 | |
parent | aec8fbfb834dfcf46b7c967d6572c9adcb72b620 (diff) | |
download | busybox-w32-6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467.tar.gz busybox-w32-6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467.tar.bz2 busybox-w32-6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467.zip |
tar: prevent malicious archives with enormous long name sizes OOMing the machine
function old new delta
get_header_tar 1707 1752 +45
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/libarchive/get_header_tar.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index a142290ff..d26868bf8 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c | |||
@@ -147,6 +147,12 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g | |||
147 | #endif | 147 | #endif |
148 | } | 148 | } |
149 | 149 | ||
150 | static void die_if_bad_fnamesize(off_t sz) | ||
151 | { | ||
152 | if ((uoff_t)sz > 0xfff) /* more than 4k?! no funny business please */ | ||
153 | bb_simple_error_msg_and_die("bad archive"); | ||
154 | } | ||
155 | |||
150 | char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | 156 | char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) |
151 | { | 157 | { |
152 | file_header_t *file_header = archive_handle->file_header; | 158 | file_header_t *file_header = archive_handle->file_header; |
@@ -331,7 +337,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
331 | file_header->name = xstrdup(tar.name); | 337 | file_header->name = xstrdup(tar.name); |
332 | } | 338 | } |
333 | 339 | ||
334 | /* Set bits 12-15 of the files mode */ | ||
335 | switch (tar_typeflag) { | 340 | switch (tar_typeflag) { |
336 | case '1': /* hardlink */ | 341 | case '1': /* hardlink */ |
337 | /* we mark hardlinks as regular files with zero size and a link name */ | 342 | /* we mark hardlinks as regular files with zero size and a link name */ |
@@ -389,7 +394,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
389 | /* free: paranoia: tar with several consecutive longnames */ | 394 | /* free: paranoia: tar with several consecutive longnames */ |
390 | free(p_longname); | 395 | free(p_longname); |
391 | /* For paranoia reasons we allocate extra NUL char */ | 396 | /* For paranoia reasons we allocate extra NUL char */ |
392 | //FIXME: disallow huge sizes: | 397 | die_if_bad_fnamesize(file_header->size); |
393 | p_longname = xzalloc(file_header->size + 1); | 398 | p_longname = xzalloc(file_header->size + 1); |
394 | /* We read ASCIZ string, including NUL */ | 399 | /* We read ASCIZ string, including NUL */ |
395 | xread(archive_handle->src_fd, p_longname, file_header->size); | 400 | xread(archive_handle->src_fd, p_longname, file_header->size); |
@@ -400,7 +405,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |||
400 | goto again; | 405 | goto again; |
401 | case 'K': | 406 | case 'K': |
402 | free(p_linkname); | 407 | free(p_linkname); |
403 | //FIXME: disallow huge sizes: | 408 | die_if_bad_fnamesize(file_header->size); |
404 | p_linkname = xzalloc(file_header->size + 1); | 409 | p_linkname = xzalloc(file_header->size + 1); |
405 | xread(archive_handle->src_fd, p_linkname, file_header->size); | 410 | xread(archive_handle->src_fd, p_linkname, file_header->size); |
406 | archive_handle->offset += file_header->size; | 411 | archive_handle->offset += file_header->size; |