diff options
author | 2017-09-27 15:22:21 -0700 | |
---|---|---|
committer | 2017-10-03 15:41:14 -0700 | |
commit | dbbe33b95336efa74e8bb4ebcf6cba50919aa247 (patch) | |
tree | 737276cbe7f1a04572eaa58ca290f19bf54d22f1 | |
parent | a932e64d699eee455e044da38f6a4109774222ea (diff) |
libui: harden GraphicBufferMapper::importBuffer
Add support for validateBufferSize and getTransportSize from IMapper
2.1. Update GraphicBufferMapper::importBuffer to validate buffer
size, and update GraphicBuffer::flatten to use the handle transport
size.
This fixes two issues with GraphicBuffer. Pointers returned by
lock/lockYCbCr can now be accessed without potential OOB. flatten
no longer includes process-local runtime data.
Bug: 62535446
Bug: 62084097
Bug: 32587089
Test: manual
Change-Id: Ice13af26b84f25e43089637e9d67e3ad820e22ed
-rw-r--r-- | libs/ui/Android.bp | 1 | ||||
-rw-r--r-- | libs/ui/Gralloc2.cpp | 52 | ||||
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 26 | ||||
-rw-r--r-- | libs/ui/GraphicBufferMapper.cpp | 33 | ||||
-rw-r--r-- | libs/ui/include/ui/Gralloc2.h | 9 | ||||
-rw-r--r-- | libs/ui/include/ui/GraphicBuffer.h | 4 | ||||
-rw-r--r-- | libs/ui/include/ui/GraphicBufferMapper.h | 6 |
7 files changed, 116 insertions, 15 deletions
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index eb2e858e25..a2664f18de 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -71,6 +71,7 @@ cc_library_shared { shared_libs: [ "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", "libbase", diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp index 0eb08e59a9..1f746a2ed1 100644 --- a/libs/ui/Gralloc2.cpp +++ b/libs/ui/Gralloc2.cpp @@ -39,9 +39,15 @@ void Mapper::preload() { Mapper::Mapper() { mMapper = IMapper::getService(); - if (mMapper == nullptr || mMapper->isRemote()) { + if (mMapper == nullptr) { + LOG_ALWAYS_FATAL("gralloc-mapper is missing"); + } + if (mMapper->isRemote()) { LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode"); } + + // IMapper 2.1 is optional + mMapperV2_1 = hardware::graphics::mapper::V2_1::IMapper::castFrom(mMapper); } Error Mapper::createDescriptor( @@ -91,6 +97,50 @@ void Mapper::freeBuffer(buffer_handle_t bufferHandle) const buffer, error); } +Error Mapper::validateBufferSize(buffer_handle_t bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, + uint32_t stride) const +{ + if (mMapperV2_1 == nullptr) { + return Error::NONE; + } + + auto buffer = const_cast<native_handle_t*>(bufferHandle); + auto ret = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride); + + return (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError; +} + +void Mapper::getTransportSize(buffer_handle_t bufferHandle, + uint32_t* outNumFds, uint32_t* outNumInts) const +{ + *outNumFds = uint32_t(bufferHandle->numFds); + *outNumInts = uint32_t(bufferHandle->numInts); + + if (mMapperV2_1 == nullptr) { + return; + } + + Error error; + auto buffer = const_cast<native_handle_t*>(bufferHandle); + auto ret = mMapperV2_1->getTransportSize(buffer, + [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) { + error = tmpError; + if (error != Error::NONE) { + return; + } + + *outNumFds = tmpNumFds; + *outNumInts = tmpNumInts; + }); + + if (!ret.isOk()) { + error = kTransactionError; + } + ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", + buffer, error); +} + Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const IMapper::Rect& accessRegion, int acquireFence, void** outData) const diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index c8805000a4..4ed2aa42fc 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -170,6 +170,8 @@ status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight, inUsage, &handle, &outStride, mId, std::move(requestorName)); if (err == NO_ERROR) { + mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); + width = static_cast<int>(inWidth); height = static_cast<int>(inHeight); format = inFormat; @@ -199,7 +201,8 @@ status_t GraphicBuffer::initWithHandle(const native_handle_t* handle, if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) { buffer_handle_t importedHandle; - status_t err = mBufferMapper.importBuffer(handle, &importedHandle); + status_t err = mBufferMapper.importBuffer(handle, width, height, + layerCount, format, usage, stride, &importedHandle); if (err != NO_ERROR) { initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0); @@ -212,6 +215,7 @@ status_t GraphicBuffer::initWithHandle(const native_handle_t* handle, } handle = importedHandle; + mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); } ANativeWindowBuffer::handle = handle; @@ -323,11 +327,11 @@ status_t GraphicBuffer::unlockAsync(int *fenceFd) } size_t GraphicBuffer::getFlattenedSize() const { - return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int); + return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int); } size_t GraphicBuffer::getFdCount() const { - return static_cast<size_t>(handle ? handle->numFds : 0); + return static_cast<size_t>(handle ? mTransportNumFds : 0); } status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const { @@ -353,18 +357,18 @@ status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& buf[12] = int(usage >> 32); // high 32-bits if (handle) { - buf[10] = handle->numFds; - buf[11] = handle->numInts; - memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int)); + buf[10] = int32_t(mTransportNumFds); + buf[11] = int32_t(mTransportNumInts); + memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int)); memcpy(buf + 13, handle->data + handle->numFds, - static_cast<size_t>(handle->numInts) * sizeof(int)); + static_cast<size_t>(mTransportNumInts) * sizeof(int)); } buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded); size -= sizeNeeded; if (handle) { - fds += handle->numFds; - count -= static_cast<size_t>(handle->numFds); + fds += mTransportNumFds; + count -= static_cast<size_t>(mTransportNumFds); } return NO_ERROR; @@ -457,7 +461,8 @@ status_t GraphicBuffer::unflatten( if (handle != 0) { buffer_handle_t importedHandle; - status_t err = mBufferMapper.importBuffer(handle, &importedHandle); + status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height), + uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle); if (err != NO_ERROR) { width = height = stride = format = usage_deprecated = 0; layerCount = 0; @@ -470,6 +475,7 @@ status_t GraphicBuffer::unflatten( native_handle_close(handle); native_handle_delete(const_cast<native_handle_t*>(handle)); handle = importedHandle; + mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); } buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index 163432821f..672dc361a1 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -52,17 +52,42 @@ GraphicBufferMapper::GraphicBufferMapper() } status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle, + uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, uint32_t stride, buffer_handle_t* outHandle) { ATRACE_CALL(); + buffer_handle_t bufferHandle; Gralloc2::Error error = mMapper->importBuffer( - hardware::hidl_handle(rawHandle), outHandle); + hardware::hidl_handle(rawHandle), &bufferHandle); + if (error != Gralloc2::Error::NONE) { + ALOGW("importBuffer(%p) failed: %d", rawHandle, error); + return static_cast<status_t>(error); + } + + Gralloc2::IMapper::BufferDescriptorInfo info = {}; + info.width = width; + info.height = height; + info.layerCount = layerCount; + info.format = static_cast<Gralloc2::PixelFormat>(format); + info.usage = usage; + error = mMapper->validateBufferSize(bufferHandle, info, stride); + if (error != Gralloc2::Error::NONE) { + ALOGE("validateBufferSize(%p) failed: %d", rawHandle, error); + freeBuffer(bufferHandle); + return static_cast<status_t>(error); + } - ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d", - rawHandle, error); + *outHandle = bufferHandle; - return static_cast<status_t>(error); + return NO_ERROR; +} + +void GraphicBufferMapper::getTransportSize(buffer_handle_t handle, + uint32_t* outTransportNumFds, uint32_t* outTransportNumInts) +{ + mMapper->getTransportSize(handle, outTransportNumFds, outTransportNumInts); } status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle) diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h index 8aee16033a..69c35f7dda 100644 --- a/libs/ui/include/ui/Gralloc2.h +++ b/libs/ui/include/ui/Gralloc2.h @@ -21,6 +21,7 @@ #include <android/hardware/graphics/allocator/2.0/IAllocator.h> #include <android/hardware/graphics/mapper/2.0/IMapper.h> +#include <android/hardware/graphics/mapper/2.1/IMapper.h> #include <utils/StrongPointer.h> namespace android { @@ -55,6 +56,13 @@ public: void freeBuffer(buffer_handle_t bufferHandle) const; + Error validateBufferSize(buffer_handle_t bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, + uint32_t stride) const; + + void getTransportSize(buffer_handle_t bufferHandle, + uint32_t* outNumFds, uint32_t* outNumInts) const; + // The ownership of acquireFence is always transferred to the callee, even // on errors. Error lock(buffer_handle_t bufferHandle, uint64_t usage, @@ -73,6 +81,7 @@ public: private: sp<IMapper> mMapper; + sp<hardware::graphics::mapper::V2_1::IMapper> mMapperV2_1; }; // A wrapper to IAllocator diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 95c2d2272e..e794462f60 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -230,6 +230,10 @@ private: GraphicBufferMapper& mBufferMapper; ssize_t mInitCheck; + // numbers of fds/ints in native_handle_t to flatten + uint32_t mTransportNumFds; + uint32_t mTransportNumInts; + uint64_t mId; // Stores the generation number of this buffer. If this number does not diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h index 06961b11b5..7cf003dcba 100644 --- a/libs/ui/include/ui/GraphicBufferMapper.h +++ b/libs/ui/include/ui/GraphicBufferMapper.h @@ -22,6 +22,7 @@ #include <memory> +#include <ui/PixelFormat.h> #include <utils/Singleton.h> @@ -49,10 +50,15 @@ public: // The imported outHandle must be freed with freeBuffer when no longer // needed. rawHandle is owned by the caller. status_t importBuffer(buffer_handle_t rawHandle, + uint32_t width, uint32_t height, uint32_t layerCount, + PixelFormat format, uint64_t usage, uint32_t stride, buffer_handle_t* outHandle); status_t freeBuffer(buffer_handle_t handle); + void getTransportSize(buffer_handle_t handle, + uint32_t* outTransportNumFds, uint32_t* outTransportNumInts); + status_t lock(buffer_handle_t handle, uint32_t usage, const Rect& bounds, void** vaddr); |