magicislab / google-security-research

Automatically exported from code.google.com/p/google-security-research
0 stars 0 forks source link

Oracle Java Runtime Environment heap corruption during TTF font rendering in fnt_IDEF #299

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
A heap corruption condition was observed in Oracle Java Runtime Environment 
version 8u40 (latest at the time of this writing) while fuzz-testing the 
processing of TrueType font files, implemented in a proprietary t2k library. It 
manifests itself in the form of a SIGSEGV crash inside of heap-related 
functions such as malloc() or free(), e.g.:

--- cut ---
$ java -cp . DisplaySfntFont sample.ttf
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f660fec412f, pid=25106, tid=140076342568704
#
# JRE version: Java(TM) SE Runtime Environment (8.0_40-b25) (build 1.8.0_40-b25)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.40-b25 mixed mode linux-amd64 
compressed oops)
# Problematic frame:
# C  [libc.so.6+0x7f12f]
(hangs)
--- cut ---

The full stack-trace at the time of the SIGSEGV is as follows:

--- cut ---
#0  0x00007ffff745c12f in _int_free (av=0x7ffff0000020, p=<optimized out>, 
have_lock=0) at malloc.c:3996
#1  0x00007fffbed76746 in tsi_EmergencyShutDown () from 
jre1.8.0_40/lib/amd64/libt2k.so
#2  0x00007fffbed67a50 in T2K_RenderGlyph () from 
jre1.8.0_40/lib/amd64/libt2k.so
#3  0x00007fffbed52d3f in Java_sun_font_T2KFontScaler_getGlyphImageNative () 
from jre1.8.0_40/lib/amd64/libt2k.so
--- cut ---

The crash reproduces on both Windows and Linux platforms (more reliably on 
Linux). The root cause of the crash is not fully known, but is probably closely 
related to the maxp.maxInstructionDefs field and defining new instructions via 
the IDEF [] instruction. The mutated testcase minimizes to a 2-byte difference, 
with one byte modified in the TTF pre-program (section "prep"), and the other 
one in the "glyf" section. Valgrind shows that there are multiple heap 
out-of-bounds memory accesses in the fnt_IDEF function on Linux:

--- cut ---
==24140== Invalid read of size 1
==24140==    at 0x2C25F12F: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==  Address 0x223b2837 is 5 bytes after a block of size 258 alloc'd
==24140==    at 0x40307C4: malloc 
(valgrind/coregrind/m_replacemalloc/vg_replace_malloc.c:270)
==24140==    by 0x2C2A5C1D: tsi_AllocMem (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2694E8: NewTTSHintcalerFont (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26981B: NewTTHintFontForT2K (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C293FB6: NewT2K (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281149: Java_sun_font_T2KFontScaler_initNativeScaler (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x775F7A6: ???
==24140==    by 0x5EA3A55: JavaCalls::call_helper(JavaValue*, methodHandle*, 
JavaCallArguments*, Thread*) (in jre1.8.0_40/lib/amd64/server/libjvm.so)
==24140==    by 0x61A7016: Reflection::invoke(instanceKlassHandle, 
methodHandle, Handle, bool, objArrayHandle, BasicType, objArrayHandle, bool, 
Thread*) (in jre1.8.0_40/lib/amd64/server/libjvm.so)
==24140==    by 0x61A7C52: Reflection::invoke_constructor(oopDesc*, 
objArrayHandle, Thread*) (in jre1.8.0_40/lib/amd64/server/libjvm.so)
==24140==
==24140== Conditional jump or move depends on uninitialised value(s)
==24140==    at 0x2C25F151: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==
==24140== Invalid read of size 1
==24140==    at 0x2C25F147: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==  Address 0x223b283f is 13 bytes after a block of size 258 alloc'd
==24140==    at 0x40307C4: malloc 
(valgrind/coregrind/m_replacemalloc/vg_replace_malloc.c:270)
==24140==    by 0x2C2A5C1D: tsi_AllocMem (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2694E8: NewTTSHintcalerFont (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26981B: NewTTHintFontForT2K (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C293FB6: NewT2K (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281149: Java_sun_font_T2KFontScaler_initNativeScaler (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x775F7A6: ???
==24140==    by 0x5EA3A55: JavaCalls::call_helper(JavaValue*, methodHandle*, 
JavaCallArguments*, Thread*) (in jre1.8.0_40/lib/amd64/server/libjvm.so)
==24140==    by 0x61A7016: Reflection::invoke(instanceKlassHandle, 
methodHandle, Handle, bool, objArrayHandle, BasicType, objArrayHandle, bool, 
Thread*) (in jre1.8.0_40/lib/amd64/server/libjvm.so)
==24140==    by 0x61A7C52: Reflection::invoke_constructor(oopDesc*, 
objArrayHandle, Thread*) (in jre1.8.0_40/lib/amd64/server/libjvm.so)
==24140==
==24140== Invalid write of size 1
==24140==    at 0x2C25F197: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==  Address 0x223b2886 is not stack'd, malloc'd or (recently) free'd
==24140==
==24140== Invalid write of size 1
==24140==    at 0x2C25F19C: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==  Address 0x223b2887 is not stack'd, malloc'd or (recently) free'd
==24140==
==24140== Invalid write of size 4
==24140==    at 0x2C25F1A8: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==  Address 0x223b2880 is not stack'd, malloc'd or (recently) free'd
==24140==
==24140== Invalid write of size 2
==24140==    at 0x2C25F1FD: fnt_IDEF (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C260A38: fnt_InnerExecute (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C26039D: fnt_Execute (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2640CC: RunPreProgram (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C262A77: TTScalerHintGlyph (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C2961E4: T2K_RenderGlyphInternal (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C29665E: T2K_RenderGlyph (in jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x2C281D3E: Java_sun_font_T2KFontScaler_getGlyphImageNative (in 
jre1.8.0_40/lib/amd64/libt2k.so)
==24140==    by 0x7774993: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==    by 0x776675F: ???
==24140==  Address 0x223b2884 is not stack'd, malloc'd or (recently) free'd
--- cut ---

Also, running Java.exe on Windows under Application Verifier (with the "Heap" 
option enabled) against a font which has more IDEF [] statements than the value 
of maxp.maxInstructionDefs also triggers an Access Violation exception.

Attached with this report is the mutated testcase together with the original 
file used to create it, and a simple Java program used to reproduce the 
vulnerability by loading TrueType/OpenType fonts specified through a 
command-line parameter.

This bug is subject to a 90 day disclosure deadline. If 90 days elapse without 
a broadly available patch, then the bug report will automatically become 
visible to the public.

Original issue reported on code.google.com by mjurc...@google.com on 25 Mar 2015 at 7:52

Attachments:

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 2 Apr 2015 at 6:15

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 10 Apr 2015 at 10:59

GoogleCodeExporter commented 9 years ago
Fixed in Oracle Critical Patch Update Advisory - April 2015, 
http://www.oracle.com/technetwork/topics/security/cpuapr2015-2365600.html.

Oracle informed us that the report was a duplicate and a patch for the issue 
was already scheduled for the April update.

Original comment by mjurc...@google.com on 15 Apr 2015 at 5:39

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 16 Apr 2015 at 3:56

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 16 Apr 2015 at 3:57

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 16 Apr 2015 at 10:20

GoogleCodeExporter commented 9 years ago

Original comment by mjurc...@google.com on 20 Apr 2015 at 11:14