diff options
6 files changed, 87 insertions, 30 deletions
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h index 843b6e3011..6ea970825b 100644 --- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h @@ -19,10 +19,14 @@ #include <android-base/unique_fd.h> #include <fuzzer/FuzzedDataProvider.h> +#include <vector> + namespace android { // always valid or aborts // get a random FD for use in fuzzing, of a few different specific types -base::unique_fd getRandomFd(FuzzedDataProvider* provider); +// +// may return multiple FDs (e.g. pipe), but will always return at least one +std::vector<base::unique_fd> getRandomFds(FuzzedDataProvider* provider); } // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h index 459fb127c2..27587a9162 100644 --- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h @@ -33,10 +33,13 @@ struct RandomParcelOptions { /** * Fill parcel data, including some random binder objects and FDs * + * May insert additional FDs/binders if they own data related to the Parcel (e.g. the other + * end of a pipe). + * * p - the Parcel to fill * provider - takes ownership and completely consumes provider * writeHeader - optional function to write a specific header once the format of the parcel is * picked (for instance, to write an interface header) */ -void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, const RandomParcelOptions& = {}); +void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOptions* options); } // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp index d5aa353af0..32494e3f77 100644 --- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp +++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp @@ -44,7 +44,7 @@ void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) { std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>( provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes())); - fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()), options); + fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()), &options); Parcel reply; (void)target->transact(code, data, &reply, flags); diff --git a/libs/binder/tests/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp index 180a177689..bef4ab6e99 100644 --- a/libs/binder/tests/parcel_fuzzer/main.cpp +++ b/libs/binder/tests/parcel_fuzzer/main.cpp @@ -35,17 +35,22 @@ #include <sys/time.h> using android::fillRandomParcel; +using android::RandomParcelOptions; using android::sp; using android::base::HexString; -void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) { +void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider, + RandomParcelOptions* options) { // TODO: functionality to create random parcels for libhwbinder parcels + (void)options; + std::vector<uint8_t> input = provider.ConsumeRemainingBytes<uint8_t>(); p->setData(input.data(), input.size()); } -static void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider) { +static void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider, + RandomParcelOptions* options) { // fill underlying parcel using functions to fill random libbinder parcel - fillRandomParcel(p->parcel(), std::move(provider)); + fillRandomParcel(p->parcel(), std::move(provider), options); } template <typename P, typename B> @@ -55,9 +60,11 @@ void doTransactFuzz(const char* backend, const sp<B>& binder, FuzzedDataProvider FUZZ_LOG() << "backend: " << backend; + RandomParcelOptions options; + P reply; P data; - fillRandomParcel(&data, std::move(provider)); + fillRandomParcel(&data, std::move(provider), &options); (void)binder->transact(code, data, &reply, flag); } @@ -73,8 +80,10 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, std::vector<uint8_t> instructions = provider.ConsumeBytes<uint8_t>( provider.ConsumeIntegralInRange<size_t>(0, maxInstructions)); + RandomParcelOptions options; + P p; - fillRandomParcel(&p, std::move(provider)); + fillRandomParcel(&p, std::move(provider), &options); // since we are only using a byte to index CHECK(reads.size() <= 255) << reads.size(); @@ -103,9 +112,12 @@ void doAppendFuzz(const char* backend, FuzzedDataProvider&& provider) { std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>( provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes())); + // same options so that FDs and binders could be shared in both Parcels + RandomParcelOptions options; + P p0, p1; - fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size())); - fillRandomParcel(&p1, std::move(provider)); + fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()), &options); + fillRandomParcel(&p1, std::move(provider), &options); FUZZ_LOG() << "backend: " << backend; FUZZ_LOG() << "start: " << start << " len: " << len; diff --git a/libs/binder/tests/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp index ab0b7e306f..3fcf104e81 100644 --- a/libs/binder/tests/parcel_fuzzer/random_fd.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_fd.cpp @@ -23,13 +23,44 @@ namespace android { -base::unique_fd getRandomFd(FuzzedDataProvider* provider) { - int fd = provider->PickValueInArray<std::function<int()>>({ - []() { return ashmem_create_region("binder test region", 1024); }, - []() { return open("/dev/null", O_RDWR); }, +using base::unique_fd; + +std::vector<unique_fd> getRandomFds(FuzzedDataProvider* provider) { + std::vector<unique_fd> fds = provider->PickValueInArray< + std::function<std::vector<unique_fd>()>>({ + [&]() { + std::vector<unique_fd> ret; + ret.push_back(unique_fd( + ashmem_create_region("binder test region", + provider->ConsumeIntegralInRange<size_t>(0, 4096)))); + return ret; + }, + [&]() { + std::vector<unique_fd> ret; + ret.push_back(unique_fd(open("/dev/null", O_RDWR))); + return ret; + }, + [&]() { + int pipefds[2]; + + int flags = O_CLOEXEC; + if (provider->ConsumeBool()) flags |= O_DIRECT; + if (provider->ConsumeBool()) flags |= O_NONBLOCK; + + CHECK_EQ(0, pipe2(pipefds, flags)); + + if (provider->ConsumeBool()) std::swap(pipefds[0], pipefds[1]); + + std::vector<unique_fd> ret; + ret.push_back(unique_fd(pipefds[0])); + ret.push_back(unique_fd(pipefds[1])); + return ret; + }, })(); - CHECK(fd >= 0); - return base::unique_fd(fd); + + for (const auto& fd : fds) CHECK(fd.ok()) << fd.get(); + + return fds; } } // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp index 0204f5ed61..51cb768d3d 100644 --- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp +++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp @@ -39,23 +39,24 @@ static void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) { CHECK(OK == p->write(data.data(), data.size())); } -void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, - const RandomParcelOptions& options) { +void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOptions* options) { + CHECK_NE(options, nullptr); + if (provider.ConsumeBool()) { auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make()); CHECK_EQ(OK, session->addNullDebuggingClient()); p->markForRpc(session); - if (options.writeHeader) { - options.writeHeader(p, provider); + if (options->writeHeader) { + options->writeHeader(p, provider); } fillRandomParcelData(p, std::move(provider)); return; } - if (options.writeHeader) { - options.writeHeader(p, provider); + if (options->writeHeader) { + options->writeHeader(p, provider); } while (provider.remaining_bytes() > 0) { @@ -69,15 +70,21 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, }, // write FD [&]() { - if (options.extraFds.size() > 0 && provider.ConsumeBool()) { - const base::unique_fd& fd = options.extraFds.at( + if (options->extraFds.size() > 0 && provider.ConsumeBool()) { + const base::unique_fd& fd = options->extraFds.at( provider.ConsumeIntegralInRange<size_t>(0, - options.extraFds.size() - + options->extraFds.size() - 1)); CHECK(OK == p->writeFileDescriptor(fd.get(), false /*takeOwnership*/)); } else { - base::unique_fd fd = getRandomFd(&provider); - CHECK(OK == p->writeFileDescriptor(fd.release(), true /*takeOwnership*/)); + std::vector<base::unique_fd> fds = getRandomFds(&provider); + CHECK(OK == + p->writeFileDescriptor(fds.begin()->release(), + true /*takeOwnership*/)); + + options->extraFds.insert(options->extraFds.end(), + std::make_move_iterator(fds.begin() + 1), + std::make_move_iterator(fds.end())); } }, // write binder @@ -98,10 +105,10 @@ void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, return IInterface::asBinder(defaultServiceManager()); }, [&]() -> sp<IBinder> { - if (options.extraBinders.size() > 0 && provider.ConsumeBool()) { - return options.extraBinders.at( + if (options->extraBinders.size() > 0 && provider.ConsumeBool()) { + return options->extraBinders.at( provider.ConsumeIntegralInRange< - size_t>(0, options.extraBinders.size() - 1)); + size_t>(0, options->extraBinders.size() - 1)); } else { return nullptr; } |