bugThe FreeType Project - Bugs: bug #41697, Out-of-bounds stack-based...

 
 

bug #41697: Out-of-bounds stack-based read/write in cf2_hintmap_build

Submitted by:  Mateusz Jurczyk <j00ru>
Submitted on:  Tue 25 Feb 2014 08:43:38 PM UTC  
 
Severity:  3 - Normal Item Group:  Crash
Status:  Fixed Privacy:  Public
Assigned to:  Dave Arnold <darnold> Open/Closed:  Closed
Planned Release:  2.5.3

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

( Jump to the original submission)

Mon 10 Mar 2014 09:20:40 AM UTC, comment #8: 

Update: you can use CVE-2014-2240 as the identifier of the vulnerability.

You can also use CVE-2014-2241 for the other fix you submitted in relation to this bug, if required (not necessary).

Thanks,
Mateusz

Mateusz Jurczyk <j00ru>
Project Member
Sat 01 Mar 2014 02:24:56 AM UTC, comment #7: 

Thanks for the quick turn-around!

There isn't a CVE available yet; MITRE can only assign them based on public information, such as the recently submitted commit.

I am going to request one and get back to you once the allocation is made.

Mateusz Jurczyk <j00ru>
Project Member
Fri 28 Feb 2014 08:30:39 AM UTC, comment #6: 

Thanks a lot for the patches!  They are now in the git repository.  Right now I'm preparing a new release, to be available in one or two days, I guess.

Is there a CVE number already available?

Werner LEMBERG <wl>
Project Administrator
Fri 28 Feb 2014 02:00:53 AM UTC, comment #5: 

The problem is triggered by a charstring with too many stem hints.

In the original font, asan_stack-oob_704686_9216_cov_3502053733_sigsegv2.ttf,
the problem occurs with glyph 15364. There are 150 stem hints.
Many incidental errors also occur:
"cff_index_access_element: offset to next entry ..."
"tt_face_build_cmaps: unsupported cmap sub-table ..."

In the second font, ftbench_oob_stack_sigsegv.otf, there are 1,000,000 stem hints in glyph 47.

The error is correctly detected, but the program flow after the error is incorrect. The simplest fix is to return early from cf2_hintmap_build() when there is an invalid hint mask.

Dave Arnold <darnold>
Project MemberIn charge of this item.
Wed 26 Feb 2014 05:33:18 PM UTC, comment #4: 

Thanks, it now crashes properly :-)

Werner LEMBERG <wl>
Project Administrator
Wed 26 Feb 2014 05:06:52 PM UTC, comment #3: 

Yes, I am pretty sure that's the right font. It's strange you have difficulty reproducing it, as the bitCount variable is clearly larger than the maximum legal value of 96 in the source code I referred to.

Anyway, here: http://j00ru.vexillium.org/dump/ftbench_oob_stack_sigsegv.otf you can find another font which crosses the stack buffer boundary not by just a few bits, but enough to reach the top of the stack and generate a SIGSEGV exception in a regular ftbench build:

--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7721bce in cf2_hintmap_build (hintmap=0x7fffffff7150, hStemHintArray=0x7fffffffd3b0, vStemHintArray=0x7fffffffd370,
    hintMask=0x7fffffff7120, hintOrigin=0, initialMap=0 '\000')
    at freetype2/src/cff/cf2hints.c:820
820       if ( maskByte & *maskPtr )
(gdb) where
#0  0x00007ffff7721bce in cf2_hintmap_build (hintmap=0x7fffffff7150, hStemHintArray=0x7fffffffd3b0, vStemHintArray=0x7fffffffd370,
    hintMask=0x7fffffff7120, hintOrigin=0, initialMap=0 '\000')
    at freetype2/src/cff/cf2hints.c:820
#1  0x00007ffff77249bd in cf2_interpT2CharString (font=0x60e5c0, buf=0x7fffffffd620, callbacks=0x60e628, translation=0x7fffffffd5d0,
    doingSeac=0 '\000', curX=0, curY=0, width=0x7fffffffd5cc)
    at freetype2/src/cff/cf2intrp.c:1201
#2  0x00007ffff771febe in cf2_getGlyphOutline (font=0x60e5c0, charstring=0x7fffffffd620, transform=0x7fffffffd650,
    glyphWidth=0x7fffffffd64c) at freetype2/src/cff/cf2font.c:461
#3  0x00007ffff77205b1 in cf2_decoder_parse_charstrings (decoder=0x7fffffffd770,
    charstring_base=0x7ffff6604df8 "\024PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001PP\001P"..., charstring_len=3000007) at freetype2/src/cff/cf2ft.c:369
#4  0x00007ffff771d8e9 in cff_slot_load (glyph=0x60c9e0, size=0x60cc40, glyph_index=47, load_flags=0)
    at freetype2/src/cff/cffgload.c:2840
#5  0x00007ffff7716013 in cff_glyph_load (cffslot=0x60c9e0, cffsize=0x60cc40, glyph_index=47, load_flags=0)
    at freetype2/src/cff/cffdrivr.c:185
#6  0x00007ffff76e6659 in FT_Load_Glyph (face=0x60a8e0, glyph_index=47, load_flags=0)
    at freetype2/src/base/ftobjs.c:726
#7  0x0000000000401acb in test_load (timer=0x7fffffffe0a0, face=0x60a8e0, user_data=0x0)
    at freetype2-demos/src/ftbench.c:249
#8  0x00000000004019f7 in benchmark (face=0x60a8e0, test=0x7fffffffe0f0, max_iter=0, max_time=2)
    at freetype2-demos/src/ftbench.c:216
#9  0x0000000000402fd8 in main (argc=1, argv=0x7fffffffe270)
    at freetype2-demos/src/ftbench.c:1020
(gdb) x/10i $rip
=> 0x7ffff7721bce <cf2_hintmap_build+493>: movzbl (%rax),%eax
   0x7ffff7721bd1 <cf2_hintmap_build+496>: and    -0x21(%rbp),%al
   0x7ffff7721bd4 <cf2_hintmap_build+499>: test   %al,%al
   0x7ffff7721bd6 <cf2_hintmap_build+501>: je     0x7ffff7721cd9 <cf2_hintmap_build+760>
   0x7ffff7721bdc <cf2_hintmap_build+507>: mov    -0xb8(%rbp),%rax
   0x7ffff7721be3 <cf2_hintmap_build+514>: mov    0x1c(%rax),%r8d
   0x7ffff7721be7 <cf2_hintmap_build+518>: mov    -0xd4(%rbp),%edi
   0x7ffff7721bed <cf2_hintmap_build+524>: mov    -0x30(%rbp),%rcx
   0x7ffff7721bf1 <cf2_hintmap_build+528>: mov    -0x20(%rbp),%rdx
   0x7ffff7721bf5 <cf2_hintmap_build+532>: mov    -0xc0(%rbp),%rsi
(gdb) x/10wx $rax
0x7ffffffff000: Cannot access memory at address 0x7ffffffff000
--- cut ---

I hope that helps, let me know if you have any luck with reproduction.

Mateusz Jurczyk <j00ru>
Project Member
Wed 26 Feb 2014 07:31:09 AM UTC, comment #2: 

Thanks for the report.  Are you sure this is the right font?  Dave Arnold can't reproduce it (and me neither, but I don't have a 64bit system – however, I get an assertion at a different place, something that should be fixed also).

It would be very helpful if you could play with ftbench's -i option to help us find the triggering glyph index.

Werner LEMBERG <wl>
Project Administrator
Tue 25 Feb 2014 08:46:32 PM UTC, comment #1: 
Mateusz Jurczyk <j00ru>
Project Member
Tue 25 Feb 2014 08:43:38 PM UTC, original submission:  

Tested on Ubuntu AMD64 with upstream FreeType2 and FreeType2-demos, reproduced with ./ftbench <file>.

This is a critical vulnerability in the CFF Rasterizer code recently contributed by Adobe, leading to potential arbitrary code execution in the context of the FreeType2 library client. It will require a CVE identifier and most likely a new stable library release.

I would like to ask you to keep the bug private until a new release is out.

Report:

==31664==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff76853d70 at pc 0x6d2d74 bp 0x7fff768537f0 sp 0x7fff768537e8
READ of size 1 at 0x7fff76853d70 thread T0
    #0 0x6d2d73 in cf2_hintmap_build freetype2/src/cff/cf2hints.c:820
    #1 0x6b85ab in cf2_interpT2CharString freetype2/src/cff/cf2intrp.c:1201
    #2 0x6ae390 in cf2_getGlyphOutline freetype2/src/cff/cf2font.c:461
    #3 0x6aafa6 in cf2_decoder_parse_charstrings freetype2/src/cff/cf2ft.c:369
    #4 0x6a134c in cff_slot_load freetype2/src/cff/cffgload.c:2840
    #5 0x66b8b0 in cff_glyph_load freetype2/src/cff/cffdrivr.c:185
    #6 0x4a28e2 in FT_Load_Glyph freetype2/src/base/ftobjs.c:726
    #7 0x492475 in test_load freetype2-demos/src/ftbench.c:249
    #8 0x4930e7 in benchmark freetype2-demos/src/ftbench.c:216
    #9 0x48f692 in main freetype2-demos/src/ftbench.c:1020

Address 0x7fff76853d70 is located in stack of thread T0 at offset 304 in frame
    #0 0x6d1c8f in cf2_hintmap_build freetype2/src/cff/cf2hints.c:754

  This frame has 20 object(s):
    [32, 40) 'hintmap.addr'
    [64, 72) 'hStemHintArray.addr'
    [96, 104) 'vStemHintArray.addr'
    [128, 136) 'hintMask.addr'
    [160, 164) 'hintOrigin.addr'
    [176, 177) 'initialMap.addr'
    [192, 200) 'maskPtr'
    [224, 232) 'font'
    [256, 304) 'tempHintMask' <== Memory access at offset 304 overflows this variable
    [336, 344) 'bitCount'
    [368, 376) 'i'
    [400, 401) 'maskByte'
    [416, 448) 'dummy'
    [480, 512) 'bottomHintEdge'
    [544, 576) 'topHintEdge'
    [608, 640) 'edge62'
    [672, 704) 'invalid'
    [736, 768) 'bottomHintEdge77'
    [800, 832) 'topHintEdge78'
    [864, 872) 'stemhint'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions are supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow freetype2/src/cff/cf2hints.c:820 cf2_hintmap_build
Shadow bytes around the buggy address:
  0x10006ed02750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10006ed02760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10006ed02770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10006ed02780: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 f2 f2 f2
  0x10006ed02790: 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 04 f2 01 f2
=>0x10006ed027a0: 00 f2 f2 f2 00 f2 f2 f2 00 00 00 00 00 00[f2]f2
  0x10006ed027b0: f2 f2 00 f2 f2 f2 00 f2 f2 f2 01 f2 00 00 00 00
  0x10006ed027c0: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00
  0x10006ed027d0: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00
  0x10006ed027e0: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00
  0x10006ed027f0: f2 f2 f2 f2 00 f3 f3 f3 00 00 00 00 00 00 00 00
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:      [31==31664==ABORTING

Root cause: no implementation for the "TODO" comment below.

--- src/cff/cf2hints.c ---
794:    /* use the hStem hints only, which are first in the mask */
795:    /* TODO: compare this to cffhintmaskGetBitCount */
796:    bitCount = cf2_arrstack_size( hStemHintArray );
--- cut ---

Mateusz Jurczyk <j00ru>
Project Member

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by darnold (Posted a comment)
  • -email is unavailable- added by wl (Updated the item)
  • -email is unavailable- added by wl
  • -email is unavailable- added by j00ru (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

     

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2014-03-07 wl PrivacyPrivate => Public
    2014-02-28 wl StatusConfirmed => Fixed
        Assigned towl => darnold
        Open/ClosedOpen => Closed
        Planned ReleaseNone => 2.5.3
    2014-02-26 wl StatusNeed Info => Confirmed
    2014-02-26 wl StatusNone => Need Info
    2014-02-25 wl Assigned toNone => wl
        Carbon-Copy- => Added darnold

    Back to the top


    Powered by Savane 3.5