binder_parcel_fuzzer: construct parcels w/ objects

Better coverage, since before we didn't test read methods that might get
ahold of valid objects. This is in preparation of exporting and using
these randomly generated parcel objects elsewhere.

Bug: N/A
Test: binder_parcel_fuzzer
Change-Id: Iac53cbe0437cea39a0d94177abe4e33d50eb189e
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
index d2b4d52..1a67898 100644
--- a/libs/binder/fuzzer/Android.bp
+++ b/libs/binder/fuzzer/Android.bp
@@ -12,6 +12,8 @@
         "binder_ndk.cpp",
         "hwbinder.cpp",
         "main.cpp",
+        "random_fd.cpp",
+        "random_parcel.cpp",
         "util.cpp",
     ],
     static_libs: [
diff --git a/libs/binder/fuzzer/binder.h b/libs/binder/fuzzer/binder.h
index b224ef4..0c51d68 100644
--- a/libs/binder/fuzzer/binder.h
+++ b/libs/binder/fuzzer/binder.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #include <binder/Parcel.h>
 #include <vector>
diff --git a/libs/binder/fuzzer/binder_ndk.h b/libs/binder/fuzzer/binder_ndk.h
index 622cafc..e69d9c1 100644
--- a/libs/binder/fuzzer/binder_ndk.h
+++ b/libs/binder/fuzzer/binder_ndk.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #include <android/binder_auto_utils.h>
 #include <vector>
@@ -31,6 +32,9 @@
     const AParcel* aParcel() const { return mParcel.get(); }
     AParcel* aParcel() { return mParcel.get(); }
 
+    android::Parcel* parcel() { return aParcel()->get(); }
+
+    const uint8_t* data() const { return aParcel()->get()->data(); }
     size_t dataSize() const { return aParcel()->get()->dataSize(); }
     size_t dataAvail() const { return aParcel()->get()->dataAvail(); }
     size_t dataPosition() const { return aParcel()->get()->dataPosition(); }
diff --git a/libs/binder/fuzzer/hwbinder.h b/libs/binder/fuzzer/hwbinder.h
index a6c66be..1fa56d4 100644
--- a/libs/binder/fuzzer/hwbinder.h
+++ b/libs/binder/fuzzer/hwbinder.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #include <hwbinder/Parcel.h>
 #include <vector>
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
index db23938..46bf417 100644
--- a/libs/binder/fuzzer/main.cpp
+++ b/libs/binder/fuzzer/main.cpp
@@ -18,6 +18,7 @@
 #include "binder.h"
 #include "binder_ndk.h"
 #include "hwbinder.h"
+#include "random_parcel.h"
 #include "util.h"
 
 #include <android-base/logging.h>
@@ -26,29 +27,33 @@
 #include <cstdlib>
 #include <ctime>
 
+using android::fillRandomParcel;
+
+void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) {
+    std::vector<uint8_t> input = provider.ConsumeRemainingBytes<uint8_t>();
+    p->setData(input.data(), input.size());
+}
+
 template <typename P>
 void doFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads,
-            FuzzedDataProvider* provider) {
+            FuzzedDataProvider&& provider) {
     // Allow some majority of the bytes to be dedicated to telling us what to
     // do. The fixed value added here represents that we want to test doing a
     // lot of 'instructions' even on really short parcels.
-    size_t maxInstructions = 20 + (provider->remaining_bytes() * 2 / 3);
+    size_t maxInstructions = 20 + (provider.remaining_bytes() * 2 / 3);
     // but don't always use that many instructions. We want to allow the fuzzer
     // to explore large parcels with few instructions if it wants to.
-    std::vector<uint8_t> instructions = provider->ConsumeBytes<uint8_t>(
-            provider->ConsumeIntegralInRange<size_t>(0, maxInstructions));
-
-    // TODO: generate 'objects' data
-    std::vector<uint8_t> input = provider->ConsumeRemainingBytes<uint8_t>();
+    std::vector<uint8_t> instructions = provider.ConsumeBytes<uint8_t>(
+            provider.ConsumeIntegralInRange<size_t>(0, maxInstructions));
 
     P p;
-    p.setData(input.data(), input.size());
+    fillRandomParcel(&p, std::move(provider));
 
     // since we are only using a byte to index
     CHECK(reads.size() <= 255) << reads.size();
 
     FUZZ_LOG() << "backend: " << backend;
-    FUZZ_LOG() << "input: " << hexString(input);
+    FUZZ_LOG() << "input: " << hexString(p.data(), p.dataSize());
     FUZZ_LOG() << "instructions: " << hexString(instructions);
 
     for (size_t i = 0; i + 1 < instructions.size(); i += 2) {
@@ -75,20 +80,22 @@
 
     FuzzedDataProvider provider = FuzzedDataProvider(data, size);
 
-    const std::function<void(FuzzedDataProvider*)> fuzzBackend[3] = {
-            [](FuzzedDataProvider* provider) {
+    const std::function<void(FuzzedDataProvider &&)> fuzzBackend[3] = {
+            [](FuzzedDataProvider&& provider) {
                 doFuzz<::android::hardware::Parcel>("hwbinder", HWBINDER_PARCEL_READ_FUNCTIONS,
-                                                    provider);
+                                                    std::move(provider));
             },
-            [](FuzzedDataProvider* provider) {
-                doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, provider);
+            [](FuzzedDataProvider&& provider) {
+                doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS,
+                                          std::move(provider));
             },
-            [](FuzzedDataProvider* provider) {
-                doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, provider);
+            [](FuzzedDataProvider&& provider) {
+                doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS,
+                                         std::move(provider));
             },
     };
 
-    provider.PickValueInArray(fuzzBackend)(&provider);
+    provider.PickValueInArray(fuzzBackend)(std::move(provider));
 
     return 0;
 }
diff --git a/libs/binder/fuzzer/parcel_fuzzer.h b/libs/binder/fuzzer/parcel_fuzzer.h
index 10cf17c..b68a8a9 100644
--- a/libs/binder/fuzzer/parcel_fuzzer.h
+++ b/libs/binder/fuzzer/parcel_fuzzer.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 template <typename P>
 using ParcelRead = std::function<void(const P& p, uint8_t data)>;
diff --git a/libs/binder/fuzzer/random_fd.cpp b/libs/binder/fuzzer/random_fd.cpp
new file mode 100644
index 0000000..eb80ece
--- /dev/null
+++ b/libs/binder/fuzzer/random_fd.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "random_fd.h"
+
+#include <fcntl.h>
+
+#include <android-base/logging.h>
+#include <cutils/ashmem.h>
+
+namespace android {
+
+int getRandomFd(FuzzedDataProvider* provider) {
+    int fd = provider->PickValueInArray<std::function<int()>>({
+            []() { return ashmem_create_region("binder test region", 1024); },
+            []() { return open("/dev/null", O_RDWR); },
+    })();
+    CHECK(fd >= 0);
+    return fd;
+}
+
+} // namespace android
diff --git a/libs/binder/fuzzer/random_fd.h b/libs/binder/fuzzer/random_fd.h
new file mode 100644
index 0000000..0a083d7
--- /dev/null
+++ b/libs/binder/fuzzer/random_fd.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+// ownership to callee, always valid or aborts
+// get a random FD for use in fuzzing, of a few different specific types
+int getRandomFd(FuzzedDataProvider* provider);
+
+} // namespace android
diff --git a/libs/binder/fuzzer/random_parcel.cpp b/libs/binder/fuzzer/random_parcel.cpp
new file mode 100644
index 0000000..3dae904
--- /dev/null
+++ b/libs/binder/fuzzer/random_parcel.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "random_parcel.h"
+
+#include "random_fd.h"
+
+#include <android-base/logging.h>
+#include <binder/IServiceManager.h>
+#include <utils/String16.h>
+
+namespace android {
+
+void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider) {
+    fillRandomParcel(p->parcel(), std::move(provider));
+}
+
+class NamedBinder : public BBinder {
+public:
+    NamedBinder(const String16& descriptor) : mDescriptor(descriptor) {}
+    const String16& getInterfaceDescriptor() const override { return mDescriptor; }
+
+private:
+    String16 mDescriptor;
+};
+
+void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider) {
+    while (provider.remaining_bytes() > 0) {
+        auto fillFunc = provider.PickValueInArray<const std::function<void()>>({
+                // write data
+                [&]() {
+                    size_t toWrite =
+                            provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes());
+                    std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(toWrite);
+                    CHECK(OK == p->write(data.data(), data.size()));
+                },
+                // write FD
+                [&]() {
+                    int fd = getRandomFd(&provider);
+                    CHECK(OK == p->writeFileDescriptor(fd, true /*takeOwnership*/));
+                },
+                // write binder
+                [&]() {
+                    auto makeFunc = provider.PickValueInArray<const std::function<sp<IBinder>()>>({
+                            [&]() {
+                                // descriptor is the length of a class name, e.g.
+                                // "some.package.Foo"
+                                std::string str =
+                                        provider.ConsumeRandomLengthString(100 /*max length*/);
+                                return new NamedBinder(String16(str.c_str()));
+                            },
+                            []() {
+                                // this is the easiest remote binder to get ahold of, and it
+                                // should be able to handle anything thrown at it, and
+                                // essentially every process can talk to it, so it's a good
+                                // candidate for checking usage of an actual BpBinder
+                                return IInterface::asBinder(defaultServiceManager());
+                            },
+                            []() { return nullptr; },
+                    });
+                    sp<IBinder> binder = makeFunc();
+                    CHECK(OK == p->writeStrongBinder(binder));
+                },
+        });
+
+        fillFunc();
+    }
+}
+
+} // namespace android
diff --git a/libs/binder/fuzzer/random_parcel.h b/libs/binder/fuzzer/random_parcel.h
new file mode 100644
index 0000000..2923c47
--- /dev/null
+++ b/libs/binder/fuzzer/random_parcel.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include "binder_ndk.h"
+
+#include <binder/Parcel.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
+void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider);
+} // namespace android
diff --git a/libs/binder/fuzzer/util.h b/libs/binder/fuzzer/util.h
index aa504d2..45e8c57 100644
--- a/libs/binder/fuzzer/util.h
+++ b/libs/binder/fuzzer/util.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #include <iostream>
 #include <sstream>