From 12b806bac0f22c0cf7e63ea95b75016a8d6e0447 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 22 Sep 2017 10:44:37 -0700 Subject: [PATCH] graphics: add IMapper@2.1 Add necessary methods to protect the framework against crafted buffer handles. Bug: 62535446 Bug: 62084097 Bug: 32587089 Test: manual Change-Id: I11486c0767a90788da9f84c2177202f26c0d9ce1 --- graphics/Android.bp | 2 + graphics/mapper/2.1/Android.bp | 149 +++++++++++ graphics/mapper/2.1/IMapper.hal | 61 +++++ graphics/mapper/2.1/vts/OWNERS | 6 + graphics/mapper/2.1/vts/functional/Android.bp | 32 +++ .../VtsHalGraphicsMapperV2_1TargetTest.cpp | 247 ++++++++++++++++++ 6 files changed, 497 insertions(+) create mode 100644 graphics/mapper/2.1/Android.bp create mode 100644 graphics/mapper/2.1/IMapper.hal create mode 100644 graphics/mapper/2.1/vts/OWNERS create mode 100644 graphics/mapper/2.1/vts/functional/Android.bp create mode 100644 graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp diff --git a/graphics/Android.bp b/graphics/Android.bp index 9aea85f6c4..9fa9241fb7 100644 --- a/graphics/Android.bp +++ b/graphics/Android.bp @@ -10,4 +10,6 @@ subdirs = [ "mapper/2.0", "mapper/2.0/default", "mapper/2.0/vts/functional", + "mapper/2.1", + "mapper/2.1/vts/functional", ] diff --git a/graphics/mapper/2.1/Android.bp b/graphics/mapper/2.1/Android.bp new file mode 100644 index 0000000000..971cd99544 --- /dev/null +++ b/graphics/mapper/2.1/Android.bp @@ -0,0 +1,149 @@ +// This file is autogenerated by hidl-gen. Do not edit manually. + +filegroup { + name: "android.hardware.graphics.mapper@2.1_hal", + srcs: [ + "IMapper.hal", + ], +} + +genrule { + name: "android.hardware.graphics.mapper@2.1_genc++", + tools: ["hidl-gen"], + cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.1", + srcs: [ + ":android.hardware.graphics.mapper@2.1_hal", + ], + out: [ + "android/hardware/graphics/mapper/2.1/MapperAll.cpp", + ], +} + +genrule { + name: "android.hardware.graphics.mapper@2.1_genc++_headers", + tools: ["hidl-gen"], + cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.1", + srcs: [ + ":android.hardware.graphics.mapper@2.1_hal", + ], + out: [ + "android/hardware/graphics/mapper/2.1/IMapper.h", + "android/hardware/graphics/mapper/2.1/IHwMapper.h", + "android/hardware/graphics/mapper/2.1/BnHwMapper.h", + "android/hardware/graphics/mapper/2.1/BpHwMapper.h", + "android/hardware/graphics/mapper/2.1/BsMapper.h", + ], +} + +cc_library { + name: "android.hardware.graphics.mapper@2.1", + defaults: ["hidl-module-defaults"], + generated_sources: ["android.hardware.graphics.mapper@2.1_genc++"], + generated_headers: ["android.hardware.graphics.mapper@2.1_genc++_headers"], + export_generated_headers: ["android.hardware.graphics.mapper@2.1_genc++_headers"], + vendor_available: true, + vndk: { + enabled: true, + support_system_process: true, + }, + shared_libs: [ + "libhidlbase", + "libhidltransport", + "libhwbinder", + "liblog", + "libutils", + "libcutils", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", + ], + export_shared_lib_headers: [ + "libhidlbase", + "libhidltransport", + "libhwbinder", + "libutils", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", + ], +} + +genrule { + name: "android.hardware.graphics.mapper@2.1-adapter-helper_genc++", + tools: ["hidl-gen"], + cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.1", + srcs: [ + ":android.hardware.graphics.mapper@2.1_hal", + ], + out: [ + "android/hardware/graphics/mapper/2.1/AMapper.cpp", + ], +} + +genrule { + name: "android.hardware.graphics.mapper@2.1-adapter-helper_genc++_headers", + tools: ["hidl-gen"], + cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.1", + srcs: [ + ":android.hardware.graphics.mapper@2.1_hal", + ], + out: [ + "android/hardware/graphics/mapper/2.1/AMapper.h", + ], +} + + +cc_library { + name: "android.hardware.graphics.mapper@2.1-adapter-helper", + defaults: ["hidl-module-defaults"], + generated_sources: ["android.hardware.graphics.mapper@2.1-adapter-helper_genc++"], + generated_headers: ["android.hardware.graphics.mapper@2.1-adapter-helper_genc++_headers"], + export_generated_headers: ["android.hardware.graphics.mapper@2.1-adapter-helper_genc++_headers"], + vendor_available: true, + shared_libs: [ + "libhidlbase", + "libhidltransport", + "libhwbinder", + "liblog", + "libutils", + "libcutils", + "libhidladapter", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@2.0-adapter-helper", + "android.hidl.base@1.0-adapter-helper", + ], + export_shared_lib_headers: [ + "libhidlbase", + "libhidltransport", + "libhwbinder", + "libutils", + "libhidladapter", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@2.0-adapter-helper", + "android.hidl.base@1.0-adapter-helper", + ], +} + +genrule { + name: "android.hardware.graphics.mapper@2.1-adapter_genc++", + tools: ["hidl-gen"], + cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-main -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.1", + out: ["main.cpp"] +} + +cc_test { + name: "android.hardware.graphics.mapper@2.1-adapter", + shared_libs: [ + "libhidladapter", + "libhidlbase", + "libhidltransport", + "libutils", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@2.1-adapter-helper", + ], + generated_sources: ["android.hardware.graphics.mapper@2.1-adapter_genc++"], +} diff --git a/graphics/mapper/2.1/IMapper.hal b/graphics/mapper/2.1/IMapper.hal new file mode 100644 index 0000000000..a23656d455 --- /dev/null +++ b/graphics/mapper/2.1/IMapper.hal @@ -0,0 +1,61 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.graphics.mapper@2.1; + +import android.hardware.graphics.mapper@2.0::Error; +import android.hardware.graphics.mapper@2.0::IMapper; + +interface IMapper extends android.hardware.graphics.mapper@2.0::IMapper { + /** + * Validate that the buffer can be safely accessed by a caller who assumes + * the specified descriptorInfo and stride. This must at least validate + * that the buffer size is large enough. Validating the buffer against + * individual buffer attributes is optional. + * + * @param buffer is the buffer to validate against. + * @param descriptorInfo specifies the attributes of the buffer. + * @param stride is the buffer stride returned by IAllocator::allocate. + * @return error is NONE upon success. Otherwise, + * BAD_BUFFER when the buffer is invalid. + * BAD_VALUE when buffer cannot be safely accessed + */ + validateBufferSize(pointer buffer, + BufferDescriptorInfo descriptorInfo, + uint32_t stride) + generates (Error error); + + /** + * Get the transport size of a buffer. An imported buffer handle is a raw + * buffer handle with the process-local runtime data appended. This + * function, for example, allows a caller to omit the process-local + * runtime data at the tail when serializing the imported buffer handle. + * + * Note that a client might or might not omit the process-local runtime + * data when sending an imported buffer handle. The mapper must support + * both cases on the receiving end. + * + * @param buffer is the buffer to get the transport size from. + * @return error is NONE upon success. Otherwise, + * BAD_BUFFER when the buffer is invalid. + * @return numFds is the number of file descriptors needed for transport. + * @return numInts is the number of integers needed for transport. + */ + getTransportSize(pointer buffer) + generates (Error error, + uint32_t numFds, + uint32_t numInts); +}; diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS new file mode 100644 index 0000000000..ef69d7cffe --- /dev/null +++ b/graphics/mapper/2.1/vts/OWNERS @@ -0,0 +1,6 @@ +# Graphics team +olv@google.com + +# VTS team +yim@google.com +zhuoyao@google.com \ No newline at end of file diff --git a/graphics/mapper/2.1/vts/functional/Android.bp b/graphics/mapper/2.1/vts/functional/Android.bp new file mode 100644 index 0000000000..578d298a19 --- /dev/null +++ b/graphics/mapper/2.1/vts/functional/Android.bp @@ -0,0 +1,32 @@ +// +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "VtsHalGraphicsMapperV2_1TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: ["VtsHalGraphicsMapperV2_1TargetTest.cpp"], + shared_libs: [ + "libsync", + ], + static_libs: [ + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.common@1.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "libVtsHalGraphicsMapperTestUtils", + "libnativehelper", + ], +} diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp new file mode 100644 index 0000000000..4067c8d3ac --- /dev/null +++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VtsHalGraphicsMapperV2_1TargetTest" + +#include +#include +#include +#include +#include "VtsHalGraphicsMapperTestUtils.h" + +namespace android { +namespace hardware { +namespace graphics { +namespace mapper { +namespace V2_1 { +namespace tests { +namespace { + +using android::hardware::graphics::mapper::V2_0::Error; + +using android::hardware::graphics::common::V1_0::BufferUsage; +using android::hardware::graphics::common::V1_0::PixelFormat; + +class Gralloc : public V2_0::tests::Gralloc { + public: + Gralloc() : V2_0::tests::Gralloc() { + if (::testing::Test::HasFatalFailure()) { + return; + } + + init(); + } + + sp getMapper() const { return mMapper; } + + bool validateBufferSize(const native_handle_t* bufferHandle, + const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride) { + auto buffer = const_cast(bufferHandle); + + Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride); + return error == Error::NONE; + } + + void getTransportSize(const native_handle_t* bufferHandle, uint32_t* numFds, + uint32_t* numInts) { + auto buffer = const_cast(bufferHandle); + + *numFds = 0; + *numInts = 0; + mMapper->getTransportSize(buffer, [&](const auto& tmpError, const auto& tmpNumFds, + const auto& tmpNumInts) { + ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size"; + ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds; + ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts; + + *numFds = tmpNumFds; + *numInts = tmpNumInts; + }); + } + + private: + void init() { + mMapper = IMapper::castFrom(V2_0::tests::Gralloc::getMapper()); + ASSERT_NE(nullptr, mMapper.get()) << "failed to find IMapper 2.1"; + } + + sp mMapper; +}; + +class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase { + protected: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); + + mDummyDescriptorInfo.width = 64; + mDummyDescriptorInfo.height = 64; + mDummyDescriptorInfo.layerCount = 1; + mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; + mDummyDescriptorInfo.usage = + static_cast(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + } + + void TearDown() override {} + + std::unique_ptr mGralloc; + IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; +}; + +/** + * Test that IMapper::validateBufferSize works. + */ +TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBasic) { + const native_handle_t* bufferHandle; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true, &stride)); + + ASSERT_TRUE(mGralloc->validateBufferSize(bufferHandle, mDummyDescriptorInfo, stride)); + + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle)); +} + +/** + * Test IMapper::validateBufferSize with invalid buffers. + */ +TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBadBuffer) { + native_handle_t* invalidHandle = nullptr; + Error ret = mGralloc->getMapper()->validateBufferSize(invalidHandle, mDummyDescriptorInfo, + mDummyDescriptorInfo.width); + ASSERT_EQ(Error::BAD_BUFFER, ret) + << "validateBufferSize with nullptr did not fail with BAD_BUFFER"; + + invalidHandle = native_handle_create(0, 0); + ret = mGralloc->getMapper()->validateBufferSize(invalidHandle, mDummyDescriptorInfo, + mDummyDescriptorInfo.width); + ASSERT_EQ(Error::BAD_BUFFER, ret) + << "validateBufferSize with invalid handle did not fail with BAD_BUFFER"; + native_handle_delete(invalidHandle); + + native_handle_t* rawBufferHandle; + ASSERT_NO_FATAL_FAILURE(rawBufferHandle = const_cast( + mGralloc->allocate(mDummyDescriptorInfo, false))); + ret = mGralloc->getMapper()->validateBufferSize(rawBufferHandle, mDummyDescriptorInfo, + mDummyDescriptorInfo.width); + ASSERT_EQ(Error::BAD_BUFFER, ret) + << "validateBufferSize with raw buffer handle did not fail with BAD_BUFFER"; + native_handle_delete(rawBufferHandle); +} + +/** + * Test IMapper::validateBufferSize with invalid descriptor and/or stride. + */ +TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBadValue) { + auto info = mDummyDescriptorInfo; + info.width = 1024; + info.height = 1024; + info.layerCount = 1; + info.format = PixelFormat::RGBA_8888; + + native_handle_t* bufferHandle; + uint32_t stride; + ASSERT_NO_FATAL_FAILURE( + bufferHandle = const_cast(mGralloc->allocate(info, true, &stride))); + + // All checks below test if a 8MB buffer can fit in a 4MB buffer. + info.width *= 2; + Error ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride); + ASSERT_EQ(Error::BAD_VALUE, ret) + << "validateBufferSize with bad width did not fail with BAD_VALUE"; + info.width /= 2; + + info.height *= 2; + ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride); + ASSERT_EQ(Error::BAD_VALUE, ret) + << "validateBufferSize with bad height did not fail with BAD_VALUE"; + info.height /= 2; + + info.layerCount *= 2; + ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride); + ASSERT_EQ(Error::BAD_VALUE, ret) + << "validateBufferSize with bad layer count did not fail with BAD_VALUE"; + info.layerCount /= 2; + + info.format = PixelFormat::RGBA_FP16; + ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride); + ASSERT_EQ(Error::BAD_VALUE, ret) + << "validateBufferSize with bad format did not fail with BAD_VALUE"; + info.format = PixelFormat::RGBA_8888; + + ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, mDummyDescriptorInfo, stride * 2); + ASSERT_EQ(Error::BAD_VALUE, ret) + << "validateBufferSize with bad stride did not fail with BAD_VALUE"; + + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle)); +} + +/** + * Test IMapper::getTransportSize. + */ +TEST_F(GraphicsMapperHidlTest, GetTransportSizeBasic) { + const native_handle_t* bufferHandle; + uint32_t numFds; + uint32_t numInts; + ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true)); + ASSERT_NO_FATAL_FAILURE(mGralloc->getTransportSize(bufferHandle, &numFds, &numInts)); + ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle)); +} + +/** + * Test IMapper::getTransportSize with invalid buffers. + */ +TEST_F(GraphicsMapperHidlTest, GetTransportSizeBadBuffer) { + native_handle_t* invalidHandle = nullptr; + mGralloc->getMapper()->getTransportSize( + invalidHandle, [&](const auto& tmpError, const auto&, const auto&) { + ASSERT_EQ(Error::BAD_BUFFER, tmpError) + << "getTransportSize with nullptr did not fail with BAD_BUFFER"; + }); + + invalidHandle = native_handle_create(0, 0); + mGralloc->getMapper()->getTransportSize( + invalidHandle, [&](const auto& tmpError, const auto&, const auto&) { + ASSERT_EQ(Error::BAD_BUFFER, tmpError) + << "getTransportSize with invalid handle did not fail with BAD_BUFFER"; + }); + native_handle_delete(invalidHandle); + + native_handle_t* rawBufferHandle; + ASSERT_NO_FATAL_FAILURE(rawBufferHandle = const_cast( + mGralloc->allocate(mDummyDescriptorInfo, false))); + mGralloc->getMapper()->getTransportSize( + invalidHandle, [&](const auto& tmpError, const auto&, const auto&) { + ASSERT_EQ(Error::BAD_BUFFER, tmpError) + << "getTransportSize with raw buffer handle did not fail with BAD_BUFFER"; + }); + native_handle_delete(rawBufferHandle); +} + +} // namespace +} // namespace tests +} // namespace V2_1 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + int status = RUN_ALL_TESTS(); + LOG(INFO) << "Test result = " << status; + + return status; +}