1 /*
2 * Copyright (C) 2016, 2018-2020 ARM Limited. All rights reserved.
3 *
4 * Copyright (C) 2008 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "mali_gralloc_reference.h"
20
21 #include <android-base/thread_annotations.h>
22 #include <hardware/gralloc1.h>
23
24 #include <algorithm>
25 #include <map>
26 #include <mutex>
27
28 #include "allocator/mali_gralloc_ion.h"
29 #include "mali_gralloc_buffer.h"
30
31 class BufferManager {
32 private:
33 // This struct for now is just for validation and reference counting. When we
34 // are sure that private_handle_t::bases is not being used outside gralloc, this
35 // should become the only place where address mapping is maintained and can be
36 // queried from.
37 struct MappedData {
38 std::array<void *, MAX_BUFFER_FDS> bases;
39 size_t alloc_sizes[MAX_BUFFER_FDS] = {};
40
41 void *metadata_vaddr;
42 size_t metadata_size;
43
44 uint64_t ref_count = 0;
45 };
46
47 BufferManager() = default;
48
49 std::mutex lock;
50 std::map<const private_handle_t *, std::unique_ptr<MappedData>> buffer_map GUARDED_BY(lock);
51
get_buffer_size(unsigned int fd)52 static off_t get_buffer_size(unsigned int fd) {
53 off_t current = lseek(fd, 0, SEEK_CUR);
54 off_t size = lseek(fd, 0, SEEK_END);
55 lseek(fd, current, SEEK_SET);
56 return size;
57 }
58
59 // TODO(b/296934447): AION buffers set the size of the buffer themselves. That size exceeds the
60 // size of the actual allocated dmabuf.
dmabuf_sanity_check(buffer_handle_t handle,bool skip_buffer_size_check=false)61 static bool dmabuf_sanity_check(buffer_handle_t handle, bool skip_buffer_size_check = false) {
62 private_handle_t *hnd =
63 static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle));
64
65 int valid_fd_count = std::find(hnd->fds, hnd->fds + MAX_FDS, -1) - hnd->fds;
66 // One fd is reserved for metadata which is not accounted for in fd_count
67 if (hnd->fd_count != valid_fd_count - 1) {
68 MALI_GRALLOC_LOGE("%s failed: count of valid buffer fds does not match fd_count",
69 __func__);
70 return false;
71 }
72
73 auto check_pid = [&](int fd, uint64_t allocated_size) -> bool {
74 auto size = get_buffer_size(fd);
75 auto size_padding = size - (off_t)allocated_size;
76 if ((size != -1) && ((size_padding < 0) || (size_padding > PAGE_SIZE))) {
77 MALI_GRALLOC_LOGE("%s failed: fd (%d) size (%jd) is not within a PAGE_SIZE of "
78 "expected size (%" PRIx64 ")",
79 __func__, fd, static_cast<intmax_t>(size), allocated_size);
80 return false;
81 }
82 return true;
83 };
84
85 // Check client facing dmabufs
86 if (!skip_buffer_size_check) {
87 for (auto i = 0; i < hnd->fd_count; i++) {
88 if (!check_pid(hnd->fds[i], hnd->alloc_sizes[i])) {
89 MALI_GRALLOC_LOGE("%s failed: Size check failed for alloc_sizes[%d]", __func__,
90 i);
91 return false;
92 }
93 }
94 }
95
96 // Check metadata dmabuf
97 if (!check_pid(hnd->get_share_attr_fd(), hnd->attr_size)) {
98 MALI_GRALLOC_LOGE("%s failed: Size check failed for metadata fd", __func__);
99 return false;
100 }
101
102 return true;
103 }
104
map_buffer_locked(buffer_handle_t handle)105 bool map_buffer_locked(buffer_handle_t handle) REQUIRES(lock) {
106 auto data_oe = get_validated_data_locked(handle);
107 if (!data_oe.has_value()) {
108 return false;
109 }
110 MappedData &data = data_oe.value();
111
112 // Return early if buffer is already mapped
113 if (data.bases[0] != nullptr) {
114 return true;
115 }
116
117 if (!dmabuf_sanity_check(handle)) {
118 return false;
119 }
120
121 private_handle_t *hnd =
122 reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
123 data.bases = mali_gralloc_ion_map(hnd);
124 if (data.bases[0] == nullptr) {
125 return false;
126 }
127
128 for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
129 data.alloc_sizes[i] = hnd->alloc_sizes[i];
130 }
131
132 return true;
133 }
134
map_metadata_locked(buffer_handle_t handle)135 bool map_metadata_locked(buffer_handle_t handle) REQUIRES(lock) {
136 auto data_oe = get_validated_data_locked(handle);
137 if (!data_oe.has_value()) {
138 return false;
139 }
140 MappedData &data = data_oe.value();
141
142 // Return early if buffer is already mapped
143 if (data.metadata_vaddr != nullptr) {
144 return true;
145 }
146
147 if (!dmabuf_sanity_check(handle, /*skip_buffer_size_check=*/true)) {
148 return false;
149 }
150
151 private_handle_t *hnd =
152 reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
153 data.metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE, MAP_SHARED,
154 hnd->get_share_attr_fd(), 0);
155 if (data.metadata_vaddr == nullptr) {
156 return false;
157 }
158
159 data.metadata_size = hnd->attr_size;
160 return true;
161 }
162
validate_locked(buffer_handle_t handle)163 bool validate_locked(buffer_handle_t handle) REQUIRES(lock) {
164 if (private_handle_t::validate(handle) < 0) {
165 MALI_GRALLOC_LOGE("Reference invalid buffer %p, returning error", handle);
166 return false;
167 }
168
169 const auto *hnd = reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
170 auto it = buffer_map.find(hnd);
171 if (it == buffer_map.end()) {
172 MALI_GRALLOC_LOGE("Reference unimported buffer %p, returning error", handle);
173 return false;
174 }
175
176 auto &data = *(it->second.get());
177 if (data.bases[0] != nullptr) {
178 for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
179 if (data.alloc_sizes[i] != hnd->alloc_sizes[i]) {
180 MALI_GRALLOC_LOGE(
181 "Validation failed: Buffer attributes inconsistent with mapper");
182 return false;
183 }
184 }
185 } else {
186 for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
187 if (data.bases[i] != nullptr) {
188 MALI_GRALLOC_LOGE("Validation failed: Expected nullptr for unmapped buffer");
189 return false;
190 }
191 }
192 }
193
194 return true;
195 }
196
get_validated_data_locked(buffer_handle_t handle)197 std::optional<std::reference_wrapper<MappedData>> get_validated_data_locked(
198 buffer_handle_t handle) REQUIRES(lock) {
199 if (!validate_locked(handle)) {
200 return {};
201 }
202
203 private_handle_t *hnd =
204 reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
205 auto it = buffer_map.find(hnd);
206 if (it == buffer_map.end()) {
207 MALI_GRALLOC_LOGE("Trying to release a non-imported buffer");
208 return {};
209 }
210
211 MappedData &data = *(it->second.get());
212 if (data.ref_count == 0) {
213 MALI_GRALLOC_LOGE("BUG: Found an imported buffer with ref count 0, expect errors");
214 }
215
216 return data;
217 }
218
219 public:
getInstance()220 static BufferManager &getInstance() {
221 static BufferManager instance;
222 return instance;
223 }
224
retain(buffer_handle_t handle)225 int retain(buffer_handle_t handle) EXCLUDES(lock) {
226 if (private_handle_t::validate(handle) < 0) {
227 MALI_GRALLOC_LOGE("Registering/Retaining invalid buffer %p, returning error", handle);
228 return -EINVAL;
229 }
230 std::lock_guard<std::mutex> _l(lock);
231
232 private_handle_t *hnd =
233 reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
234
235 auto it = buffer_map.find(hnd);
236 if (it == buffer_map.end()) {
237 bool success = false;
238 auto _data = std::make_unique<MappedData>();
239
240 std::tie(it, success) = buffer_map.insert({hnd, std::move(_data)});
241 if (!success) {
242 MALI_GRALLOC_LOGE("Failed to create buffer data mapping");
243 return -EINVAL;
244 }
245 } else if (it->second->ref_count == 0) {
246 MALI_GRALLOC_LOGE("BUG: Import counter of an imported buffer is 0, expect errors");
247 }
248 auto &data = *(it->second.get());
249
250 data.ref_count++;
251 return 0;
252 }
253
map(buffer_handle_t handle)254 int map(buffer_handle_t handle) EXCLUDES(lock) {
255 std::lock_guard<std::mutex> _l(lock);
256 if (!map_buffer_locked(handle)) {
257 return -EINVAL;
258 }
259
260 return 0;
261 }
262
release(buffer_handle_t handle)263 int release(buffer_handle_t handle) EXCLUDES(lock) {
264 std::lock_guard<std::mutex> _l(lock);
265
266 auto data_oe = get_validated_data_locked(handle);
267 if (!data_oe.has_value()) {
268 return -EINVAL;
269 }
270 MappedData &data = data_oe.value();
271
272 if (data.ref_count == 0) {
273 MALI_GRALLOC_LOGE("BUG: Reference held for buffer whose counter is 0");
274 return -EINVAL;
275 }
276
277 data.ref_count--;
278 if (data.ref_count == 0) {
279 private_handle_t *hnd =
280 reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
281 auto it = buffer_map.find(hnd);
282
283 if (data.bases[0] != nullptr) {
284 mali_gralloc_ion_unmap(hnd, data.bases);
285 }
286
287 if (data.metadata_vaddr != nullptr) {
288 munmap(data.metadata_vaddr, data.metadata_size);
289 data.metadata_vaddr = nullptr;
290 }
291
292 buffer_map.erase(it);
293 }
294
295 return 0;
296 }
297
validate(buffer_handle_t handle)298 int validate(buffer_handle_t handle) EXCLUDES(lock) {
299 std::lock_guard<std::mutex> _l(lock);
300
301 if (!validate_locked(handle)) {
302 return -EINVAL;
303 }
304
305 return 0;
306 }
307
get_buf_addr(buffer_handle_t handle)308 std::optional<void *> get_buf_addr(buffer_handle_t handle) {
309 std::lock_guard<std::mutex> _l(lock);
310
311 auto data_oe = get_validated_data_locked(handle);
312 if (!data_oe.has_value()) {
313 return {};
314 }
315 MappedData &data = data_oe.value();
316
317 if (data.bases[0] == nullptr) {
318 MALI_GRALLOC_LOGE("BUG: Called %s for an un-mapped buffer", __FUNCTION__);
319 return {};
320 }
321
322 return data.bases[0];
323 }
324
get_metadata_addr(buffer_handle_t handle)325 std::optional<void *> get_metadata_addr(buffer_handle_t handle) {
326 std::lock_guard<std::mutex> _l(lock);
327
328 auto data_oe = get_validated_data_locked(handle);
329 if (!data_oe.has_value()) {
330 return {};
331 }
332 MappedData &data = data_oe.value();
333
334 if (data.metadata_vaddr == nullptr) {
335 if (!map_metadata_locked(handle)) {
336 return {};
337 }
338 }
339
340 return data.metadata_vaddr;
341 }
342 };
343
mali_gralloc_reference_retain(buffer_handle_t handle)344 int mali_gralloc_reference_retain(buffer_handle_t handle) {
345 return BufferManager::getInstance().retain(handle);
346 }
347
mali_gralloc_reference_map(buffer_handle_t handle)348 int mali_gralloc_reference_map(buffer_handle_t handle) {
349 return BufferManager::getInstance().map(handle);
350 }
351
mali_gralloc_reference_release(buffer_handle_t handle)352 int mali_gralloc_reference_release(buffer_handle_t handle) {
353 return BufferManager::getInstance().release(handle);
354 }
355
mali_gralloc_reference_validate(buffer_handle_t handle)356 int mali_gralloc_reference_validate(buffer_handle_t handle) {
357 return BufferManager::getInstance().validate(handle);
358 }
359
mali_gralloc_reference_get_buf_addr(buffer_handle_t handle)360 std::optional<void *> mali_gralloc_reference_get_buf_addr(buffer_handle_t handle) {
361 return BufferManager::getInstance().get_buf_addr(handle);
362 }
363
mali_gralloc_reference_get_metadata_addr(buffer_handle_t handle)364 std::optional<void *> mali_gralloc_reference_get_metadata_addr(buffer_handle_t handle) {
365 return BufferManager::getInstance().get_metadata_addr(handle);
366 }
367