Bug 697459 - Heap buffer overflow in fill_threshhold_buffer()
Summary: Heap buffer overflow in fill_threshhold_buffer()
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: Security (public) (show other bugs)
Version: unspecified
Hardware: PC Linux
: P1 blocker
Assignee: Ray Johnston
Depends on:
Reported: 2016-12-31 07:26 UTC by Kamil Frankowicz
Modified: 2019-05-08 13:40 UTC (History)
5 users (show)

See Also:
Word Size: ---


Note You need to log in before you can comment on or make changes to this bug.
Description Kamil Frankowicz 2016-12-31 07:26:00 UTC
Created attachment 13269 [details]
POC to trigger heap buffer overflow (gs)

After some fuzz testing I found a crashing test case.

Version 9.20 and Git Head: 73060a27e554f8e64ae2aba4a1b03822207346c7

Command: gs -dNOPAUSE -sDEVICE=bit -sOUTPUTFILE=/dev/null -dSAFER gs_uaf_pdf14_cleanup_parent_color_profiles -c quit


==428==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f0c2a6dd4a8 at pc 0x000000504477 bp 0x7fff71316cf0 sp 0x7fff71316498
WRITE of size 16 at 0x7f0c2a6dd4a8 thread T0
    #0 0x504476 in memcpy /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:458:3
    #1 0x17c7149 in fill_threshhold_buffer XYZ/ghostpdl/./base/gxht_thresh.c:766:9
    #2 0x17c7149 in gxht_thresh_planes XYZ/ghostpdl/./base/gxht_thresh.c:908
    #3 0x64458d in image_render_color_thresh XYZ/ghostpdl/./base/gxicolor.c:854:12
    #4 0x17cd22e in gx_image1_plane_data XYZ/ghostpdl/./base/gxidata.c:211:16
    #5 0x145922d in gs_image_next_planes XYZ/ghostpdl/./base/gsimage.c:609:20
    #6 0x1b11e1f in image_proc_continue XYZ/ghostpdl/./psi/zimage.c:452:16
    #7 0x19fc122 in interp XYZ/ghostpdl/./psi/interp.c:1201:28
    #8 0x19fc122 in gs_call_interp XYZ/ghostpdl/./psi/interp.c:511
    #9 0x19fc122 in gs_interpret XYZ/ghostpdl/./psi/interp.c:468
    #10 0x19d1352 in gs_main_interpret XYZ/ghostpdl/./psi/imain.c:245:12
    #11 0x19d1352 in gs_main_run_string_end XYZ/ghostpdl/./psi/imain.c:663
    #12 0x19d1352 in gs_main_run_string_with_length XYZ/ghostpdl/./psi/imain.c:621
    #13 0x19dd2eb in run_string XYZ/ghostpdl/./psi/imainarg.c:977:16
    #14 0x19dd2eb in runarg XYZ/ghostpdl/./psi/imainarg.c:967
    #15 0x19dc748 in argproc XYZ/ghostpdl/./psi/imainarg.c:900:16
    #16 0x19d5283 in gs_main_init_with_args XYZ/ghostpdl/./psi/imainarg.c:238:24
    #17 0x5475d8 in main XYZ/ghostpdl/./psi/gs.c:96:16
    #18 0x7f0c7673d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #19 0x47b9d8 in _start (/usr/local/bin/gs+0x47b9d8)

0x7f0c2a6dd4a8 is located 0 bytes to the right of 1225297064-byte region [0x7f0be1654800,0x7f0c2a6dd4a8)
allocated by thread T0 here:
    #0 0x51a1ec in malloc /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64:3
    #1 0x1469abf in gs_heap_alloc_bytes XYZ/ghostpdl/./base/gsmalloc.c:183:34

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/development/llvm/3.9.0/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:458:3 in memcpy
Shadow bytes around the buggy address:
  0x0fe2054d3a40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe2054d3a50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe2054d3a60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe2054d3a70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe2054d3a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0fe2054d3a90: 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa fa
  0x0fe2054d3aa0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0fe2054d3ab0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0fe2054d3ac0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0fe2054d3ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0fe2054d3ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
Comment 2 Kamil Frankowicz 2017-03-01 00:12:24 UTC
Is anyone here?
Comment 3 Kamil Frankowicz 2017-04-03 23:11:26 UTC
This is CVE-2016-10317.
Comment 4 Ray Johnston 2017-04-04 07:12:17 UTC
This occurs on linux 64-bit builds, not on Windows 64-bit or 32-bit builds
since the fast ht_thresh logic doesn't happen if an earlier allocation fails
because of 32-bit limits (int on 64-bit Windows is still 32-bit, but is 64
bits on 64-bit linux build).

Thanks to Ken for replicating the problem and identifying the system

Note that I've bumped this up to P2 because it is a buffer overflow.
Comment 5 Raphaël Hertzog 2017-04-07 01:06:20 UTC
Is it on purpose that the attachment is private here while it was public for all other reports of Kamil?

Is there any ETA for the fix?

Also the command line in the first comment mentions a reproducer file named "gs_uaf_pdf14_cleanup_parent_color_profiles" but this is unlikely to be the correct name since that function does not appear in the back trace posted in the same comment.

Thank you in advance.
Comment 6 Raphaël Hertzog 2017-05-12 01:24:26 UTC
Is there any news? It would be nice to have a patch for this security issue. Thank you!
Comment 7 Marcus Meissner 2017-07-10 07:48:51 UTC
Comment 8 Ray Johnston 2017-11-21 13:33:36 UTC
This was due to an overflow calculating the size of the thresh_buffer.

Fix awaiting review:

Comment 9 Ray Johnston 2017-11-21 21:28:28 UTC
Fixed by commit 362ec9daadb9992b0def3520cd1dc6fa52edd1c4
Author: Ray Johnston <ray.johnston@artifex.com>
Date:   Tue Nov 21 12:48:54 2017 -0800

    Fix bug 697459 Buffer overflow in fill_threshold_buffer

    There was an overflow check for ht_buffer size, but none for the larger
    threshold_buffer. Note that this file didn't fail on Windows because the
    combination of the ht_buffer and the size of the (miscalculated due to
    overflow) threshold_buffer would have exceeded the 2Gb limit.