• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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