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
Touch seeded packages, which is subscribed to libarchive in 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

Status in libarchive package in Ubuntu:
  New

Bug description:
  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)

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

-- 
Mailing list: https://launchpad.net/~touch-packages
Post to     : touch-packages@lists.launchpad.net
Unsubscribe : https://launchpad.net/~touch-packages
More help   : https://help.launchpad.net/ListHelp

Reply via email to