From 6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Oct 2021 19:28:39 +0200 Subject: [PATCH] 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 --- archival/libarchive/get_header_tar.c | 11 ++++++++--- 1 file 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 #endif } +static void die_if_bad_fnamesize(off_t sz) +{ + if ((uoff_t)sz > 0xfff) /* more than 4k?! no funny business please */ + bb_simple_error_msg_and_die("bad archive"); +} + char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) { file_header_t *file_header = archive_handle->file_header; @@ -331,7 +337,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) file_header->name = xstrdup(tar.name); } - /* Set bits 12-15 of the files mode */ switch (tar_typeflag) { case '1': /* hardlink */ /* 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) /* free: paranoia: tar with several consecutive longnames */ free(p_longname); /* For paranoia reasons we allocate extra NUL char */ -//FIXME: disallow huge sizes: + die_if_bad_fnamesize(file_header->size); p_longname = xzalloc(file_header->size + 1); /* We read ASCIZ string, including NUL */ 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) goto again; case 'K': free(p_linkname); -//FIXME: disallow huge sizes: + die_if_bad_fnamesize(file_header->size); p_linkname = xzalloc(file_header->size + 1); xread(archive_handle->src_fd, p_linkname, file_header->size); archive_handle->offset += file_header->size;