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
diff --git a/graphics/Android.bp b/graphics/Android.bp
index 9aea85f..9fa9241 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -10,4 +10,6 @@
"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 0000000..971cd99
--- /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 0000000..a23656d
--- /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 0000000..ef69d7c
--- /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 0000000..578d298
--- /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 0000000..4067c8d
--- /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 <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <sync/sync.h>
+#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<IMapper> getMapper() const { return mMapper; }
+
+ bool validateBufferSize(const native_handle_t* bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride) {
+ auto buffer = const_cast<native_handle_t*>(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<native_handle_t*>(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<IMapper> mMapper;
+};
+
+class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+
+ mDummyDescriptorInfo.width = 64;
+ mDummyDescriptorInfo.height = 64;
+ mDummyDescriptorInfo.layerCount = 1;
+ mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+ mDummyDescriptorInfo.usage =
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+ }
+
+ void TearDown() override {}
+
+ std::unique_ptr<Gralloc> 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<native_handle_t*>(
+ 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<native_handle_t*>(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<native_handle_t*>(
+ 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;
+}