/* * Copyright (C) 2019 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 FUZZ_LOG_TAG "hwbinder" #include "hwbinder.h" #include "util.h" #include #include #include "../../Utils.h" using ::android::status_t; using ::android::HexString; // TODO: support scatter-gather types std::ostream& operator<<(std::ostream& os, const ::android::sp<::android::hardware::IBinder>& binder) { os << binder.get(); return os; } #define PARCEL_READ_OPT_STATUS(T, FUN) \ PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN) #define PARCEL_READ_NO_STATUS(T, FUN) \ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status"; \ T t = p.FUN(); \ FUZZ_LOG() << #T " value: " << t; \ } #define PARCEL_READ_WITH_STATUS(T, FUN) \ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t; \ status_t status = p.FUN(&t); \ FUZZ_LOG() << #T " status: " << status << " value: " << t; \ } // clang-format off std::vector> HWBINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, dataSize), PARCEL_READ_NO_STATUS(size_t, dataAvail), PARCEL_READ_NO_STATUS(size_t, dataPosition), PARCEL_READ_NO_STATUS(size_t, dataCapacity), [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange(0, INT32_MAX); FUZZ_LOG() << "about to setDataPosition: " << pos; p.setDataPosition(pos); FUZZ_LOG() << "setDataPosition done"; }, [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to enforceInterface"; bool okay = p.enforceInterface(provider.ConsumeRandomLengthString().c_str()); FUZZ_LOG() << "enforceInterface status: " << okay; }, PARCEL_READ_NO_STATUS(size_t, objectsCount), [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { // Read at least a bit. Unbounded allocation would OOM. size_t length = provider.ConsumeIntegralInRange(0, 1024); FUZZ_LOG() << "about to read"; std::vector data (length); status_t status = p.read(data.data(), length); FUZZ_LOG() << "read status: " << status << " data: " << HexString(data.data(), data.size()); }, [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t length = provider.ConsumeIntegral(); FUZZ_LOG() << "about to read"; const void* inplace = p.readInplace(length); FUZZ_LOG() << "read status: " << (inplace ? HexString(inplace, length) : "null"); }, PARCEL_READ_WITH_STATUS(int8_t, readInt8), PARCEL_READ_WITH_STATUS(uint8_t, readUint8), PARCEL_READ_WITH_STATUS(int16_t, readInt16), PARCEL_READ_WITH_STATUS(uint16_t, readUint16), PARCEL_READ_OPT_STATUS(int32_t, readInt32), PARCEL_READ_OPT_STATUS(uint32_t, readUint32), PARCEL_READ_OPT_STATUS(int64_t, readInt64), PARCEL_READ_OPT_STATUS(uint64_t, readUint64), PARCEL_READ_OPT_STATUS(float, readFloat), PARCEL_READ_OPT_STATUS(double, readDouble), PARCEL_READ_OPT_STATUS(bool, readBool), [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readCString"; const char* str = p.readCString(); FUZZ_LOG() << "readCString " << (str ? str : ""); }, PARCEL_READ_OPT_STATUS(::android::String16, readString16), PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16), [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString16Inplace"; size_t outSize = 0; const char16_t* str = p.readString16Inplace(&outSize); FUZZ_LOG() << "readString16Inplace: " << HexString(str, sizeof(char16_t) * outSize); }, PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder), PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder), [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral(); FUZZ_LOG() << "about to readBuffer"; size_t handle = 0; const void* data = nullptr; status_t status = p.readBuffer(size, &handle, &data); FUZZ_LOG() << "readBuffer status: " << status << " handle: " << handle << " data: " << data; // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral(); FUZZ_LOG() << "about to readNullableBuffer"; size_t handle = 0; const void* data = nullptr; status_t status = p.readNullableBuffer(size, &handle, &data); FUZZ_LOG() << "readNullableBuffer status: " << status << " handle: " << handle << " data: " << data; // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral(); FUZZ_LOG() << "about to readEmbeddedBuffer"; size_t handle = 0; size_t parent_buffer_handle = 0; size_t parent_offset = 3; const void* data = nullptr; status_t status = p.readEmbeddedBuffer(size, &handle, parent_buffer_handle, parent_offset, &data); FUZZ_LOG() << "readEmbeddedBuffer status: " << status << " handle: " << handle << " data: " << data; // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral(); FUZZ_LOG() << "about to readNullableEmbeddedBuffer"; size_t handle = 0; size_t parent_buffer_handle = 0; size_t parent_offset = 3; const void* data = nullptr; status_t status = p.readNullableEmbeddedBuffer(size, &handle, parent_buffer_handle, parent_offset, &data); FUZZ_LOG() << "readNullableEmbeddedBuffer status: " << status << " handle: " << handle << " data: " << data; // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readNativeHandleNoDup"; const native_handle_t* handle = nullptr; status_t status = p.readNativeHandleNoDup(&handle); FUZZ_LOG() << "readNativeHandleNoDup status: " << status << " handle: " << handle; // should be null since we don't create any IPC objects CHECK(handle == nullptr) << handle; CHECK(status != ::android::OK); }, }; // clang-format on