summaryrefslogtreecommitdiff
path: root/gralloc4/src/core/mali_gralloc_reference.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gralloc4/src/core/mali_gralloc_reference.cpp')
-rw-r--r--gralloc4/src/core/mali_gralloc_reference.cpp217
1 files changed, 153 insertions, 64 deletions
diff --git a/gralloc4/src/core/mali_gralloc_reference.cpp b/gralloc4/src/core/mali_gralloc_reference.cpp
index b84cbb4..6726895 100644
--- a/gralloc4/src/core/mali_gralloc_reference.cpp
+++ b/gralloc4/src/core/mali_gralloc_reference.cpp
@@ -35,8 +35,12 @@ private:
// should become the only place where address mapping is maintained and can be
// queried from.
struct MappedData {
- void *bases[MAX_BUFFER_FDS] = {};
+ std::array<void *, MAX_BUFFER_FDS> bases;
size_t alloc_sizes[MAX_BUFFER_FDS] = {};
+
+ void *metadata_vaddr;
+ size_t metadata_size;
+
uint64_t ref_count = 0;
};
@@ -52,7 +56,9 @@ private:
return size;
}
- static bool dmabuf_sanity_check(buffer_handle_t handle) {
+ // TODO(b/296934447): AION buffers set the size of the buffer themselves. That size exceeds the
+ // size of the actual allocated dmabuf.
+ static bool dmabuf_sanity_check(buffer_handle_t handle, bool skip_buffer_size_check = false) {
private_handle_t *hnd =
static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle));
@@ -77,10 +83,13 @@ private:
};
// Check client facing dmabufs
- for (auto i = 0; i < hnd->fd_count; i++) {
- if (!check_pid(hnd->fds[i], hnd->alloc_sizes[i])) {
- MALI_GRALLOC_LOGE("%s failed: Size check failed for alloc_sizes[%d]", __func__, i);
- return false;
+ if (!skip_buffer_size_check) {
+ for (auto i = 0; i < hnd->fd_count; i++) {
+ if (!check_pid(hnd->fds[i], hnd->alloc_sizes[i])) {
+ MALI_GRALLOC_LOGE("%s failed: Size check failed for alloc_sizes[%d]", __func__,
+ i);
+ return false;
+ }
}
}
@@ -93,75 +102,118 @@ private:
return true;
}
- int map_locked(buffer_handle_t handle) REQUIRES(lock) {
- private_handle_t *hnd = (private_handle_t *)handle;
- auto it = buffer_map.find(hnd);
-
- if (it == buffer_map.end()) {
- MALI_GRALLOC_LOGE("BUG: Map called without importing buffer");
- return -EINVAL;
- }
-
- auto &data = *(it->second.get());
- if (data.ref_count == 0) {
- MALI_GRALLOC_LOGE("BUG: Found an imported buffer with ref count 0, expect errors");
+ bool map_buffer_locked(buffer_handle_t handle) REQUIRES(lock) {
+ auto data_oe = get_validated_data_locked(handle);
+ if (!data_oe.has_value()) {
+ return false;
}
+ MappedData &data = data_oe.value();
// Return early if buffer is already mapped
if (data.bases[0] != nullptr) {
- return 0;
+ return true;
}
if (!dmabuf_sanity_check(handle)) {
- return -EINVAL;
+ return false;
}
- int error = mali_gralloc_ion_map(hnd);
- if (error != 0) {
- return error;
+ private_handle_t *hnd =
+ reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
+ data.bases = mali_gralloc_ion_map(hnd);
+ if (data.bases[0] == nullptr) {
+ return false;
}
for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
- data.bases[i] = reinterpret_cast<void *>(hnd->bases[i]);
data.alloc_sizes[i] = hnd->alloc_sizes[i];
}
- return 0;
+ return true;
}
- int validate_locked(buffer_handle_t handle) REQUIRES(lock) {
+ bool map_metadata_locked(buffer_handle_t handle) REQUIRES(lock) {
+ auto data_oe = get_validated_data_locked(handle);
+ if (!data_oe.has_value()) {
+ return false;
+ }
+ MappedData &data = data_oe.value();
+
+ // Return early if buffer is already mapped
+ if (data.metadata_vaddr != nullptr) {
+ return true;
+ }
+
+ if (!dmabuf_sanity_check(handle, /*skip_buffer_size_check=*/true)) {
+ return false;
+ }
+
+ private_handle_t *hnd =
+ reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
+ data.metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ hnd->get_share_attr_fd(), 0);
+ if (data.metadata_vaddr == nullptr) {
+ return false;
+ }
+
+ data.metadata_size = hnd->attr_size;
+ return true;
+ }
+
+ bool validate_locked(buffer_handle_t handle) REQUIRES(lock) {
if (private_handle_t::validate(handle) < 0) {
MALI_GRALLOC_LOGE("Reference invalid buffer %p, returning error", handle);
- return -EINVAL;
+ return false;
}
- const auto *hnd = (private_handle_t *)handle;
+ const auto *hnd = reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
auto it = buffer_map.find(hnd);
if (it == buffer_map.end()) {
MALI_GRALLOC_LOGE("Reference unimported buffer %p, returning error", handle);
- return -EINVAL;
+ return false;
}
auto &data = *(it->second.get());
if (data.bases[0] != nullptr) {
for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
- if (data.bases[i] != reinterpret_cast<void *>(hnd->bases[i]) ||
- data.alloc_sizes[i] != hnd->alloc_sizes[i]) {
+ if (data.alloc_sizes[i] != hnd->alloc_sizes[i]) {
MALI_GRALLOC_LOGE(
"Validation failed: Buffer attributes inconsistent with mapper");
- return -EINVAL;
+ return false;
}
}
} else {
for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
- if (hnd->bases[i] != 0 || data.bases[i] != nullptr) {
+ if (data.bases[i] != nullptr) {
MALI_GRALLOC_LOGE("Validation failed: Expected nullptr for unmapped buffer");
- return -EINVAL;
+ return false;
}
}
}
- return 0;
+ return true;
+ }
+
+ std::optional<std::reference_wrapper<MappedData>> get_validated_data_locked(
+ buffer_handle_t handle) REQUIRES(lock) {
+ if (!validate_locked(handle)) {
+ return {};
+ }
+
+ private_handle_t *hnd =
+ reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
+ auto it = buffer_map.find(hnd);
+ if (it == buffer_map.end()) {
+ MALI_GRALLOC_LOGE("Trying to release a non-imported buffer");
+ return {};
+ }
+
+ MappedData &data = *(it->second.get());
+ if (data.ref_count == 0) {
+ MALI_GRALLOC_LOGE("BUG: Found an imported buffer with ref count 0, expect errors");
+ }
+
+ return data;
}
public:
@@ -177,7 +229,8 @@ public:
}
std::lock_guard<std::mutex> _l(lock);
- private_handle_t *hnd = (private_handle_t *)handle;
+ private_handle_t *hnd =
+ reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
auto it = buffer_map.find(hnd);
if (it == buffer_map.end()) {
@@ -189,10 +242,6 @@ public:
MALI_GRALLOC_LOGE("Failed to create buffer data mapping");
return -EINVAL;
}
-
- for (int i = 0; i < MAX_BUFFER_FDS; i++) {
- hnd->bases[i] = 0;
- }
} else if (it->second->ref_count == 0) {
MALI_GRALLOC_LOGE("BUG: Import counter of an imported buffer is 0, expect errors");
}
@@ -204,34 +253,22 @@ public:
int map(buffer_handle_t handle) EXCLUDES(lock) {
std::lock_guard<std::mutex> _l(lock);
- auto error = validate_locked(handle);
- if (error != 0) {
- return error;
+ if (!map_buffer_locked(handle)) {
+ return -EINVAL;
}
- return map_locked(handle);
+ return 0;
}
int release(buffer_handle_t handle) EXCLUDES(lock) {
std::lock_guard<std::mutex> _l(lock);
- // Always call locked variant of validate from this function. On calling
- // the other validate variant, an attacker might launch a timing attack
- // where they would try to time their attack between the return of
- // validate and before taking the lock in this function again.
- auto error = validate_locked(handle);
- if (error != 0) {
- return error;
- }
-
- private_handle_t *hnd = (private_handle_t *)handle;
- auto it = buffer_map.find(hnd);
- if (it == buffer_map.end()) {
- MALI_GRALLOC_LOGE("Trying to release a non-imported buffer");
+ auto data_oe = get_validated_data_locked(handle);
+ if (!data_oe.has_value()) {
return -EINVAL;
}
+ MappedData &data = data_oe.value();
- auto &data = *(it->second.get());
if (data.ref_count == 0) {
MALI_GRALLOC_LOGE("BUG: Reference held for buffer whose counter is 0");
return -EINVAL;
@@ -239,15 +276,19 @@ public:
data.ref_count--;
if (data.ref_count == 0) {
+ private_handle_t *hnd =
+ reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
+ auto it = buffer_map.find(hnd);
+
if (data.bases[0] != nullptr) {
- mali_gralloc_ion_unmap(hnd);
+ mali_gralloc_ion_unmap(hnd, data.bases);
}
- /* TODO: Make this unmapping of shared meta fd into a function? */
- if (hnd->attr_base) {
- munmap(hnd->attr_base, hnd->attr_size);
- hnd->attr_base = nullptr;
+ if (data.metadata_vaddr != nullptr) {
+ munmap(data.metadata_vaddr, data.metadata_size);
+ data.metadata_vaddr = nullptr;
}
+
buffer_map.erase(it);
}
@@ -256,7 +297,47 @@ public:
int validate(buffer_handle_t handle) EXCLUDES(lock) {
std::lock_guard<std::mutex> _l(lock);
- return validate_locked(handle);
+
+ if (!validate_locked(handle)) {
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ std::optional<void *> get_buf_addr(buffer_handle_t handle) {
+ std::lock_guard<std::mutex> _l(lock);
+
+ auto data_oe = get_validated_data_locked(handle);
+ if (!data_oe.has_value()) {
+ return {};
+ }
+ MappedData &data = data_oe.value();
+
+ if (data.bases[0] == nullptr) {
+ MALI_GRALLOC_LOGE("BUG: Called %s for an un-mapped buffer", __FUNCTION__);
+ return {};
+ }
+
+ return data.bases[0];
+ }
+
+ std::optional<void *> get_metadata_addr(buffer_handle_t handle) {
+ std::lock_guard<std::mutex> _l(lock);
+
+ auto data_oe = get_validated_data_locked(handle);
+ if (!data_oe.has_value()) {
+ return {};
+ }
+ MappedData &data = data_oe.value();
+
+ if (data.metadata_vaddr == nullptr) {
+ if (!map_metadata_locked(handle)) {
+ return {};
+ }
+ }
+
+ return data.metadata_vaddr;
}
};
@@ -275,3 +356,11 @@ int mali_gralloc_reference_release(buffer_handle_t handle) {
int mali_gralloc_reference_validate(buffer_handle_t handle) {
return BufferManager::getInstance().validate(handle);
}
+
+std::optional<void *> mali_gralloc_reference_get_buf_addr(buffer_handle_t handle) {
+ return BufferManager::getInstance().get_buf_addr(handle);
+}
+
+std::optional<void *> mali_gralloc_reference_get_metadata_addr(buffer_handle_t handle) {
+ return BufferManager::getInstance().get_metadata_addr(handle);
+}