Home | History | Annotate | Download | only in media
      1 <html devsite>
      2   <head>
      3     <title>Media Framework Hardening</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 
     26 <p>To improve device security, Android 7.0 breaks up the monolithic
     27 <code>mediaserver</code> process into multiple processes with permissions and
     28 capabilities restricted to only those required by each process. These changes
     29 mitigate media framework security vulnerabilities by:</p>
     30 <ul>
     31 <li>Splitting AV pipeline components into app-specific sandboxed processes.</li>
     32 <li>Enabling updatable media components (extractors, codecs, etc.).</li>
     33 </ul>
     34 
     35 <p>These changes also improve security for end users by significantly reducing
     36 the severity of most media-related security vulnerabilities, keeping end user
     37 devices and data safe.</p>
     38 
     39 <p>OEMs and SoC vendors need to update their HAL and framework changes to make
     40 them compatible with the new architecture. Specifically, because vendor-provided
     41 Android code often assumes everything runs in the same process, vendors must
     42 update their code to pass around native handles (<code>native_handle</code>)
     43 that have meaning across processes. For a reference implementation of changes
     44 related to media hardening, refer to <code>frameworks/av</code> and
     45 <code>frameworks/native</code>.</p>
     46 
     47 <h2 id=arch_changes>Architectural changes</h2>
     48 <p>Previous versions of Android used a single, monolithic
     49 <code>mediaserver</code> process with great many permissions (camera access,
     50 audio access, video driver access, file access, network access, etc.). Android
     51 7.0 splits the <code>mediaserver</code> process into several new processes that
     52 each require a much smaller set of permissions:</p>
     53 
     54 <p><img src="images/ape_media_split.png" alt="mediaserver hardening"></p>
     55 <p class="img-caption"><strong>Figure 1.</strong> Architecture changes for
     56 mediaserver hardening</p>
     57 
     58 <p>This new architecture ensures that even if a process is compromised,
     59 malicious code does not have access to the full set of permissions previously
     60 held by mediaserver. Processes are restricted by SElinux and seccomp policies.
     61 </p>
     62 
     63 <p class=note><strong>Note:</strong> Because of vendor dependencies, some codecs
     64 still run in the <code>mediaserver</code> and consequently grant
     65 <code>mediaserver</code> more permissions than necessary. Specifically, Widevine
     66 Classic continues to run in the <code>mediaserver</code> for Android 7.0.</p>
     67 
     68 <h3 id=mediaserver-changes>MediaServer changes</h3>
     69 <p>In Android 7.0, the <code>mediaserver</code> process exists for driving
     70 playback and recording, e.g. passing and synchronizing buffers between
     71 components and processes. Processes communicate through the standard Binder
     72 mechanism.</p>
     73 <p>In a standard local file playback session, the application passes a file
     74 descriptor (FD) to <code>mediaserver</code> (usually via the MediaPlayer Java
     75 API), and the <code>mediaserver</code>:</p>
     76 <ol>
     77 <li>Wraps the FD into a Binder DataSource object that is passed to the extractor
     78 process, which uses it to read from the file using Binder IPC. (The
     79 mediaextractor doesn't get the FD but instead makes Binder calls back to the
     80 <code>mediaserver</code> to get the data.)</li>
     81 <li>Examines the file, creates the appropriate extractor for the file type
     82 (e.g. MP3Extractor, or MPEG4Extractor), and returns a Binder interface for the
     83 extractor to the <code>mediaserver</code> process.</li>
     84 <li>Makes Binder IPC calls to the extractor to determine the type of data in the
     85 file (e.g. MP3 or H.264 data).</li>
     86 <li>Calls into the <code>mediacodec</code> process to create codecs of the
     87 required type; receives Binder interfaces for these codecs.</li>
     88 <li>Makes repeated Binder IPC calls to the extractor to read encoded samples,
     89 uses the Binder IPC to send encoded data to the <code>mediacodec</code> process
     90 for decoding, and receives decoded data.</li>
     91 </ol>
     92 <p>In some use cases, no codec is involved (such as an offloaded playback where
     93 encoded data is sent directly to the output device), or the codec may render the
     94 decoded data directly instead of returning a buffer of decoded data (video
     95 playback).</p>
     96 
     97 <h3 id=mediacodecservice_changes>MediaCodecService changes</h3>
     98 <p>The codec service is where encoders and decoders live. Due to vendor
     99 dependencies, not all codecs live in the codec process yet. In Android 7.0:</p>
    100 <ul>
    101 <li>Non-secure decoders and software encoders live in the codec process.</li>
    102 <li>Secure decoders and hardware encoders live in the <code>mediaserver</code>
    103 (unchanged).</li>
    104 </ul>
    105 
    106 <p>An application (or mediaserver) calls the codec process to create a codec of
    107 the required type, then calls that codec to pass in encoded data and retrieve
    108 decoded data (for decoding) or to pass in decoded data and retrieve encoded data
    109 (for encoding). Data transfer to and from codecs uses shared memory already, so
    110 that process is unchanged.</p>
    111 
    112 <h3 id=mediadrmserver_changes>MediaDrmServer changes</h3>
    113 <p>The DRM server is used when playing DRM-protected content, such as movies in
    114 Google Play Movies. It handles decrypting the encrypted data in a secure way,
    115 and as such has access to certificate and key storage and other sensitive
    116 components. Due to vendor dependencies, the DRM process is not used in all cases
    117 yet.</p>
    118 
    119 <h3 id=audioserver_changes>AudioServer changes</h3>
    120 <p>The AudioServer process hosts audio related components such as audio input
    121 and output, the policymanager service that determines audio routing, and FM
    122 radio service. For details on Audio changes and implementation guidance, see
    123 <a href="/devices/audio/implement.html">Implementing Audio</a>.</p>
    124 
    125 <h3 id=cameraserver_changes>CameraServer changes</h3>
    126 <p>The CameraServer controls the camera and is used when recording video to
    127 obtain video frames from the camera and then pass them to
    128 <code>mediaserver</code> for further handling. For details on changes and
    129 implementation guidance for CameraServer changes, refer to
    130 <a href="/devices/camera/versioning.html#hardening">Camera Framework
    131 Hardening</a>.</p>
    132 
    133 <h3 id=extractor_service_changes>ExtractorService changes</h3>
    134 <p>The extractor service hosts the <em>extractors</em>, components that parse
    135 the various file formats supported by the media framework. The extractor service
    136 is the least privileged of all the services&mdash;it can't read FDs so instead
    137 it makes calls onto a Binder interface (provided to it by the
    138 <code>mediaserver for</code> each playback session) to access files.</p>
    139 <p>An application (or <code>mediaserver</code>) makes a call to the extractor
    140 process to obtain an <code>IMediaExtractor</code>, calls that
    141 <code>IMediaExtractor</code> to obtain<code> IMediaSources</code> for the track
    142 contained in the file, and then calls <code>IMediaSources</code> to read data
    143 from them.</p>
    144 <p>To transfer the data between processes, the application (or
    145 <code>mediaserver</code>) includes the data in the reply-Parcel as part of the
    146 Binder transaction or uses shared memory:</p>
    147 
    148 <ul>
    149 <li>Using <strong>shared memory</strong> requires an extra Binder call to
    150 release the shared memory but is faster and uses less power for large buffers.
    151 </li>
    152 <li>Using <strong>in-Parcel</strong> requires extra copying but is faster and
    153 uses less power for buffers smaller than 64KB.</li>
    154 </ul>
    155 
    156 <h2 id=implementation>Implementation</h2>
    157 <p>To support the move of <code>MediaDrm</code> and <code>MediaCrypto</code>
    158 components into the new <code>mediadrmserver</code> process, vendors must change
    159 the allocation method for secure buffers to allow buffers to be shared between
    160 processes.</p>
    161 <p>In previous Android releases, secure buffers are allocated in
    162 <code>mediaserver</code> by <code>OMX::allocateBuffer</code> and used during
    163 decryption in the same process, as shown below:</p>
    164 
    165 <p><img src="images/ape_media_buffer_alloc_pren.png"></p>
    166 <p class="img-caption"><strong>Figure 2.</strong> Android 6.0 and lower buffer
    167 allocation in mediaserver.</p>
    168 
    169 <p>In Android 7.0, the buffer allocation process has changed to a new mechanism
    170 that provides flexibility while minimizing the impact on existing
    171 implementations. With <code>MediaDrm</code> and <code>MediaCrypto</code> stacks
    172 in the new <code>mediadrmserver</code> process, buffers are allocated
    173 differently and vendors must update the secure buffer handles so they can be
    174 transported across binder when <code>MediaCodec</code> invokes a decrypt
    175 operation on <code>MediaCrypto</code>.</p>
    176 
    177 <p><img src="images/ape_media_buffer_alloc_n.png"></p>
    178 <p class="img-caption"><strong>Figure 3.</strong> Android 7.0 and higher buffer
    179 allocation in mediaserver.</p>
    180 
    181 <h3 id=native_handles>Using native handles</h3>
    182 <p>The <code>OMX::allocateBuffer</code> must return a pointer to a
    183 <code>native_handle</code> struct, which contains file descriptors (FDs) and
    184 additional integer data. A <code>native_handle</code> has all of the advantages
    185 of using FDs, including existing binder support for
    186 serialization/deserialization, while allowing more flexibility for vendors who
    187 don't currently use FDs.</p>
    188 <p>Use <code>native_handle_create()</code> to allocate the native handle.
    189 Framework code takes ownership of the allocated <code>native_handle</code>
    190 struct and is responsible for releasing resources in both the process where
    191 the <code>native_handle</code> is originally allocated and in the process where
    192 it is deserialized. The framework releases native handles with
    193 <code>native_handle_close()</code> followed by
    194 <code>native_handle_delete()</code> and serializes/deserializes the
    195 <code>native_handle</code> using
    196 <code>Parcel::writeNativeHandle()/readNativeHandle()</code>.
    197 </p>
    198 <p>SoC vendors who use FDs to represent secure buffers can populate the FD in
    199 the <code>native_handle</code> with their FD. Vendors who don't use FDs can
    200 represent secure buffers using additional fields in the
    201 <code>native_buffer</code>.</p>
    202 
    203 <h3 id=decrypt_location>Setting decryption location</h3>
    204 <p>Vendors must update the OEMCrypto decrypt method that operates on the
    205 <code>native_handle</code> to perform any vendor-specific operations necessary
    206 to make the <code>native_handle</code> usable in the new process space (changes
    207 typically include updates to OEMCrypto libraries).</p>
    208 <p>As <code>allocateBuffer</code> is a standard OMX operation, Android 7.0
    209 includes a new OMX extension
    210 (<code>OMX.google.android.index.allocateNativeHandle</code>) to query for this
    211 support and an <code>OMX_SetParameter</code> call that notifies the OMX
    212 implementation it should use native handles.</p>
    213 
    214   </body>
    215 </html>
    216