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