Public bug reported:

Description:

An error in archive_wstring_append_from_mbs() (archive_string.c)
triggers an out-of-bounds read memory access that results into a crash,
via a specially crafted archive file. This bug was found using our
custom fuzzer.

Basic Information:
Version of libarchive: libarchive-3.4.0, libarchive-3.4.1dev
How you obtained it: build from source
libarchive-3.4.0.tar.gz (https://www.libarchive.org/)
libarchive-3.4.1dev (https://github.com/libarchive/libarchive)
Tested operating system and version: Linux 4.15.0-65-generic x86_64
Tested compilers versions: gcc (version 7.4.0) and clang (version 
6.0.0-1ubuntu2)

============
Command to reproduce the bug using valgrind:

$ valgrind -v ./bsdtar -t -f crash_file_1  (in the attachment)

Output (partial):

bsdtar: (null)
bsdtar: Error exit delayed from previous errors.

HEAP SUMMARY:
     in use at exit: 0 bytes in 0 blocks
   total heap usage: 89 allocs, 89 frees, 285,279 bytes allocated
 
 All heap blocks were freed -- no leaks are possible
 
 ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
 
 2 errors in context 1 of 1:
 Invalid read of size 1
    at 0x5081825: utf8_internal_loop_single (loop.c:427)
    by 0x5081825: __gconv_transform_utf8_internal (skeleton.c:563)
    by 0x5116B12: mbrtowc (mbrtowc.c:86)
    by 0x14D998: archive_wstring_append_from_mbs (archive_string.c:622)
    by 0x14E19B: archive_mstring_get_wcs (archive_string.c:3941)
    by 0x116EF5: archive_entry_pathname_w (archive_entry.c:586)
    by 0x148297: zip_read_local_file_header 
(archive_read_support_format_zip.c:1038)
    by 0x1487EC: archive_read_format_zip_streamable_read_header 
(archive_read_support_format_zip.c:3083)
    by 0x11E1AB: _archive_read_next_header2 (archive_read.c:658)
    by 0x11E2FE: _archive_read_next_header (archive_read.c:696)
    by 0x112725: read_archive (read.c:260)
    by 0x112E1F: tar_mode_t (read.c:94)
    by 0x1114C6: main (bsdtar.c:913)
  Address 0x5490f47 is 0 bytes after a block of size 167 alloc'd
    at 0x4C2FA3F: malloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    by 0x4C31D84: realloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    by 0x14A6E3: archive_string_ensure (archive_string.c:314)
    by 0x14A78A: archive_string_append (archive_string.c:203)
    by 0x14DF0D: archive_strncat_l (archive_string.c:1980)
    by 0x14E4C5: archive_strncpy_l (archive_string.c:1944)
    by 0x14E4C5: archive_mstring_copy_mbs_len_l (archive_string.c:4153)
    by 0x147D95: zip_read_local_file_header 
(archive_read_support_format_zip.c:995)
    by 0x1487EC: archive_read_format_zip_streamable_read_header 
(archive_read_support_format_zip.c:3083)
    by 0x11E1AB: _archive_read_next_header2 (archive_read.c:658)
    by 0x11E2FE: _archive_read_next_header (archive_read.c:696)
    by 0x112725: read_archive (read.c:260)
    by 0x112E1F: tar_mode_t (read.c:94)
 
 ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)

---------------------------------------------------------------

Possible cause:

In archive_wstring_append_from_mbs() (archive_string.c):

int archive_wstring_append_from_mbs(struct archive_wstring *dest,
    const char *p, size_t len){
    ...
    const char *mbs = p;
    ...
    while (*mbs && mbs_length > 0) {
    ...
    ...
    r = mbrtowc(wcs, mbs, wcs_length, &shift_state);
    ...
    if (r == (size_t)-1 || r == (size_t)-2) {
                        ret_val = -1;
                        if (errno == EILSEQ) {
                                ++mbs;
                                --mbs_length;
                                continue;
                        } else
                                break;
                }
    ...
    ...
    }
}

mbrtowc() function is called with the following parameter values: wcs_length = 
3, mbs_length = 1, mbs = 0x7ffff6a43ffe "\212".
r = mbrtowc(wcs, mbs, wcs_length, &shift_state);

Here, "mbs" has a length of 1 byte, while, mbrtowc() tends to read 3 bytes 
(wcs_length = 3), thus resulting into memory out of bounds read.
The program crashes due to memory access violation, which can cause denial of 
service.

The values {wcs_length = 3, mbs_length = 1} are reached, if return value
of mbrtowc() is r = -1 or r = -2 in the previous iteration of the while
loop. "mbs" pointer increases (++mbs), and "mbs_length" length decreases
(--mbs_length), but wcs_length remains constant (3 bytes in this case).

------------------------------------------------

ProblemType: Bug
DistroRelease: Ubuntu 16.04
Package: bsdtar 3.1.2-11ubuntu0.16.04.7
ProcVersionSignature: Ubuntu 4.4.0-166.195-generic 4.4.194
Uname: Linux 4.4.0-166-generic x86_64
NonfreeKernelModules: openafs nvidia_uvm nvidia_drm nvidia_modeset nvidia
ApportVersion: 2.20.1-0ubuntu2.21
Architecture: amd64
CurrentDesktop: Unity
Date: Fri Nov  8 11:58:45 2019
SourcePackage: libarchive
UpgradeStatus: No upgrade log present (probably fresh install)

** Affects: libarchive (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: amd64 apport-bug xenial

** Attachment added: "crash_file_1"
   
https://bugs.launchpad.net/bugs/1851867/+attachment/5303891/+files/crash_file_1

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1851867

Title:
  bsdtar: An error in archive_wstring_append_from_mbs()
  (archive_string.c) allows out-of-bounds read memory access and
  subsequently cause a crash

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/libarchive/+bug/1851867/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to