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