kevinmel2000 / google-security-research

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

Android media sonivox XMF heap corruption #376

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The "sonivox" external library is used by Android to process MIDI
files. A memory corruption issue exists in the DLSParser function,
which is called via the EAS_Prepare public API. The issue is caused
while processing Extensible Music Files (XMF) using the MediaPlayer or
MediaScannerConnection APIs. Specifically, EAS_Prepare is called via
MediaPlayer.prepare/MediaPlayer.getDuration and
MediaScannerConnection.scanFile.

In practice we've triggered the heap corruption on a Nexus device
(build LMY47D) in the following scenarios:

- Forcing a ".xmf" file to be auto-downloaded by Chrome, which will
then be processed by the media scanner service.

- Clicking on an attachment in Gmail.

In general, many other application specific attack vectors may be
possible depending on the specific usage of the media APIs. A local
attack to obtain "media" UID via the mediaserver is also possible.

The vulnerability is caused by the following size calculation on an
allocation in DLSParser (eas_mdls.c):

        /* calculate final memory size */
        size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize +
artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize;
        if (size <= 0) {
            return EAS_ERROR_FILE_FORMAT;
        }

        /* allocate the main EAS chunk */
        dls.pDLS = EAS_HWMalloc(dls.hwInstData, size);
        if (dls.pDLS == NULL)
        {
            { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc
failed for DLS memory allocation size %ld\n", size); */ }
            return EAS_ERROR_MALLOC_FAILED;
        }

Note that instSize, rgnPoolSize, artPoolSize and waveLenSize are all
adequately bounded. However the dls.wavePoolSize value comes from an
attacker controlled value in an earlier function:

static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32
pos, EAS_U16 waveIndex)
{
...
    EAS_I32 dataSize = 0;
...
    while (pos < endChunk)
    {
        chunkPos = pos;

        /* get the chunk type */
        if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
            return result;

        /* parse useful chunks */
        switch (temp)
        {
...
            case CHUNK_DATA:
                dataPos = chunkPos + 8;
                dataSize = size;
                break;

            default:
                break;
        }
    }

In this circumstance, the dataSize value is set to an attacker
controlled value. This value could include negative values, so long as
the position indicator is kept in range of the file data (i.e. the
possible negative values is bounded to the attacker controlled file
size). A negative dataSize value passes the following erroneous bounds
check, since dataSize is signed:

    // limit to reasonable size
    if (dataSize > MAX_DLS_WAVE_SIZE)
    {
        return EAS_ERROR_SOUND_LIBRARY;
    }

And then finally the wavePoolSize is updated from an initial value of zero:

    if (pDLSData->pDLS == NULL)
    {
        pDLSData->wavePoolSize += (EAS_U32) size;
        return EAS_SUCCESS;
    }

In practice this means that the size calculation in DLSParser can be
made to allocate a small buffer, for example by setting wavePoolSize
to -(instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize)). At
this point, any write operations to the dls.pDLS structure can be used
to corrupt heap data. A mix of controlled-value writes and constant
value writes at different offsets are available to an attacker.

Attached is a sample XMF file that was hand crafted to trigger a small
amount of corruption using this issue. A suggested patch
(sonivox_dls_wave_size_fix.patch) is also attached.

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 haw...@google.com on 12 May 2015 at 8:25

Attachments:

GoogleCodeExporter commented 8 years ago
Fixed in AOSP here: 
https://android.googlesource.com/platform/external/sonivox/+/e999f077f6ef59d2028
2f1e04786816a31fb8be6

Fixed in Nexus Build: 5.1.1 (LMY48I)

Original comment by haw...@google.com on 11 Aug 2015 at 8:38