Merge "Adjust obb path to be able calculate external's codeSize well wo/quota"
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2c2a1b6..9b685f9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -992,6 +992,10 @@
mServiceFuzzing = true;
}
+bool Parcel::isServiceFuzzing() const {
+ return mServiceFuzzing;
+}
+
binder::Status Parcel::enforceNoDataAvail() const {
if (!mEnforceNoDataAvail) {
return binder::Status::ok();
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 5c1b230..bac2808 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -63,6 +63,7 @@
case RpcSession::FileDescriptorTransportMode::TRUSTY:
return true;
}
+ LOG_ALWAYS_FATAL("Invalid FileDescriptorTransportMode: %d", static_cast<int>(mode));
}
RpcState::RpcState() {}
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 15bb325..4e231ed 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -152,6 +152,7 @@
// When fuzzing, we want to remove certain ABI checks that cause significant
// lost coverage, and we also want to avoid logs that cost too much to write.
void setServiceFuzzing();
+ bool isServiceFuzzing() const;
void freeData();
@@ -265,7 +266,8 @@
status_t writeEnumVector(const std::optional<std::vector<T>>& val)
{ return writeData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")))
+ [[deprecated("use std::optional version instead")]] //
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val)
{ return writeData(val); }
// Write an Enum vector with underlying type != int8_t.
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
@@ -275,17 +277,20 @@
status_t writeEnumVector(const std::optional<std::vector<T>>& val)
{ return writeData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")))
+ [[deprecated("use std::optional version instead")]] //
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val)
{ return writeData(val); }
template<typename T>
status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val)
{ return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
+ [[deprecated("use std::optional version instead")]] //
+ status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val)
{ return writeData(val); }
template<typename T>
- status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
+ [[deprecated("use std::optional version instead")]] //
+ status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val)
{ return writeData(val); }
template<typename T>
status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val)
@@ -421,7 +426,8 @@
status_t readEnumVector(std::vector<T>* val) const
{ return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
+ [[deprecated("use std::optional version instead")]] //
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const
{ return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
status_t readEnumVector(std::optional<std::vector<T>>* val) const
@@ -431,7 +437,8 @@
status_t readEnumVector(std::vector<T>* val) const
{ return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
- status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
+ [[deprecated("use std::optional version instead")]] //
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const
{ return readData(val); }
template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
status_t readEnumVector(std::optional<std::vector<T>>* val) const
@@ -442,8 +449,9 @@
std::optional<std::vector<std::optional<T>>>* val) const
{ return readData(val); }
template<typename T>
+ [[deprecated("use std::optional version instead")]] //
status_t readParcelableVector(
- std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")))
+ std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const
{ return readData(val); }
template<typename T>
status_t readParcelableVector(std::vector<T>* val) const
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index d0de7b9..f7dd9c9 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -137,7 +137,7 @@
// since it's an error condition. Do the comparison after we take the lock and
// check the pointer equality fast path. By always taking the lock, it's also
// more flake-proof. However, the check is not dependent on the lock.
- if (descriptor != newDescriptor) {
+ if (descriptor != newDescriptor && !(asABpBinder() && asABpBinder()->isServiceFuzzing())) {
if (getBinder()->isBinderAlive()) {
LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor
<< "' but descriptor is actually '" << SanitizeString(descriptor) << "'.";
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 67bb092..9d5368f 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -104,10 +104,14 @@
::android::sp<::android::IBinder> getBinder() override { return mRemote; }
ABpBinder* asABpBinder() override { return this; }
+ bool isServiceFuzzing() const { return mServiceFuzzing; }
+ void setServiceFuzzing() { mServiceFuzzing = true; }
+
private:
friend android::sp<ABpBinder>;
explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
::android::sp<::android::IBinder> mRemote;
+ bool mServiceFuzzing = false;
};
struct AIBinder_Class {
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 9949de2..6273804 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -138,6 +138,8 @@
/**
* Dumps information about the interface. By default, dumps nothing.
+ *
+ * This method is not given ownership of the FD.
*/
virtual inline binder_status_t dump(int fd, const char** args, uint32_t numArgs);
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index b5a2e2f..037aa2e 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -270,6 +270,13 @@
}
sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
AIBinder_incStrong(ret.get());
+
+ if (ret.get() != nullptr && parcel->get()->isServiceFuzzing()) {
+ if (auto bp = ret->asABpBinder(); bp != nullptr) {
+ bp->setServiceFuzzing();
+ }
+ }
+
*binder = ret.get();
return PruneStatusT(status);
}
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index 0067a20..788abc4 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -75,7 +75,6 @@
visibility: [":__subpackages__"],
source_stem: "bindings",
bindgen_flags: [
- "--size_t-is-usize",
"--blocklist-type",
"AIBinder",
"--raw-line",
diff --git a/libs/binder/rust/tests/parcel_fuzzer/random_parcel/Android.bp b/libs/binder/rust/tests/parcel_fuzzer/random_parcel/Android.bp
index 43a3094..5cac647 100644
--- a/libs/binder/rust/tests/parcel_fuzzer/random_parcel/Android.bp
+++ b/libs/binder/rust/tests/parcel_fuzzer/random_parcel/Android.bp
@@ -11,7 +11,6 @@
source_stem: "bindings",
visibility: [":__subpackages__"],
bindgen_flags: [
- "--size_t-is-usize",
"--allowlist-function",
"createRandomParcel",
"--allowlist-function",
diff --git a/libs/binder/tests/binderRpcTestFixture.h b/libs/binder/tests/binderRpcTestFixture.h
index 6cde9f7..0b8920b 100644
--- a/libs/binder/tests/binderRpcTestFixture.h
+++ b/libs/binder/tests/binderRpcTestFixture.h
@@ -79,6 +79,7 @@
expectAlreadyShutdown = true;
}
+ BinderRpcTestProcessSession(std::unique_ptr<ProcessSession> proc) : proc(std::move(proc)){};
BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
~BinderRpcTestProcessSession() {
if (!expectAlreadyShutdown) {
@@ -138,9 +139,7 @@
}
BinderRpcTestProcessSession createRpcTestSocketServerProcess(const BinderRpcOptions& options) {
- BinderRpcTestProcessSession ret{
- .proc = createRpcTestSocketServerProcessEtc(options),
- };
+ BinderRpcTestProcessSession ret(createRpcTestSocketServerProcessEtc(options));
ret.rootBinder = ret.proc->sessions.empty() ? nullptr : ret.proc->sessions.at(0).root;
ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder);
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
index 24a9345..45c3a90 100644
--- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -33,6 +33,10 @@
.extraFds = {},
};
+ // always refresh the calling identity, because we sometimes set it below, but also,
+ // the code we're fuzzing might reset it
+ IPCThreadState::self()->clearCallingIdentity();
+
// Always take so that a perturbation of just the one ConsumeBool byte will always
// take the same path, but with a different UID. Without this, the fuzzer needs to
// guess both the change in value and the shift at the same time.
@@ -43,72 +47,45 @@
}
while (provider.remaining_bytes() > 0) {
- provider.PickValueInArray<std::function<void()>>({
- [&]() {
- // Most of the AIDL services will have small set of transaction codes.
- uint32_t code = provider.ConsumeBool()
- ? provider.ConsumeIntegral<uint32_t>()
- : provider.ConsumeIntegralInRange<uint32_t>(0, 100);
- uint32_t flags = provider.ConsumeIntegral<uint32_t>();
- Parcel data;
- // for increased fuzz coverage
- data.setEnforceNoDataAvail(false);
- data.setServiceFuzzing();
+ // Most of the AIDL services will have small set of transaction codes.
+ uint32_t code = provider.ConsumeBool() ? provider.ConsumeIntegral<uint32_t>()
+ : provider.ConsumeIntegralInRange<uint32_t>(0, 100);
+ uint32_t flags = provider.ConsumeIntegral<uint32_t>();
+ Parcel data;
+ // for increased fuzz coverage
+ data.setEnforceNoDataAvail(false);
+ data.setServiceFuzzing();
- sp<IBinder> target = options.extraBinders.at(
- provider.ConsumeIntegralInRange<size_t>(0,
- options.extraBinders.size() -
- 1));
- options.writeHeader = [&target](Parcel* p, FuzzedDataProvider& provider) {
- // most code will be behind checks that the head of the Parcel
- // is exactly this, so make it easier for fuzzers to reach this
- if (provider.ConsumeBool()) {
- p->writeInterfaceToken(target->getInterfaceDescriptor());
- }
- };
+ sp<IBinder> target = options.extraBinders.at(
+ provider.ConsumeIntegralInRange<size_t>(0, options.extraBinders.size() - 1));
+ options.writeHeader = [&target](Parcel* p, FuzzedDataProvider& provider) {
+ // most code will be behind checks that the head of the Parcel
+ // is exactly this, so make it easier for fuzzers to reach this
+ if (provider.ConsumeBool()) {
+ p->writeInterfaceToken(target->getInterfaceDescriptor());
+ }
+ };
- 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);
+ 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);
- Parcel reply;
- // for increased fuzz coverage
- reply.setEnforceNoDataAvail(false);
- reply.setServiceFuzzing();
- (void)target->transact(code, data, &reply, flags);
+ Parcel reply;
+ // for increased fuzz coverage
+ reply.setEnforceNoDataAvail(false);
+ reply.setServiceFuzzing();
+ (void)target->transact(code, data, &reply, flags);
- // feed back in binders and fds that are returned from the service, so that
- // we can fuzz those binders, and use the fds and binders to feed back into
- // the binders
- auto retBinders = reply.debugReadAllStrongBinders();
- options.extraBinders.insert(options.extraBinders.end(), retBinders.begin(),
- retBinders.end());
- auto retFds = reply.debugReadAllFileDescriptors();
- for (size_t i = 0; i < retFds.size(); i++) {
- options.extraFds.push_back(base::unique_fd(dup(retFds[i])));
- }
- },
- [&]() {
- if (options.extraFds.size() == 0) {
- return;
- }
- uint32_t toDelete =
- provider.ConsumeIntegralInRange<uint32_t>(0,
- options.extraFds.size() - 1);
- options.extraFds.erase(options.extraFds.begin() + toDelete);
- },
- [&]() {
- if (options.extraBinders.size() <= 1) {
- return;
- }
- uint32_t toDelete =
- provider.ConsumeIntegralInRange<uint32_t>(0,
- options.extraBinders.size() -
- 1);
- options.extraBinders.erase(options.extraBinders.begin() + toDelete);
- },
- })();
+ // feed back in binders and fds that are returned from the service, so that
+ // we can fuzz those binders, and use the fds and binders to feed back into
+ // the binders
+ auto retBinders = reply.debugReadAllStrongBinders();
+ options.extraBinders.insert(options.extraBinders.end(), retBinders.begin(),
+ retBinders.end());
+ auto retFds = reply.debugReadAllFileDescriptors();
+ for (size_t i = 0; i < retFds.size(); i++) {
+ options.extraFds.push_back(base::unique_fd(dup(retFds[i])));
+ }
}
// invariants
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl b/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl
index 3eadc02..5089ae5 100644
--- a/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/ITestService.aidl
@@ -21,4 +21,6 @@
void setCharData(char input);
void setBooleanData(boolean input);
-}
\ No newline at end of file
+
+ void setService(ITestService service);
+}
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp b/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
index 8907ea0..7fbf2d0 100644
--- a/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
@@ -17,35 +17,102 @@
#include <BnTestService.h>
#include <fuzzbinder/libbinder_driver.h>
+#include <binder/IPCThreadState.h>
#include <log/log.h>
-using android::fuzzService;
-using android::sp;
using android::binder::Status;
namespace android {
+
+enum class CrashType {
+ NONE,
+ ON_PLAIN,
+ ON_BINDER,
+ ON_KNOWN_UID,
+};
+
// This service is to verify that fuzzService is functioning properly
class TestService : public BnTestService {
public:
- Status setIntData(int /*input*/) {
- LOG_ALWAYS_FATAL("Expected crash in setIntData");
+ TestService(CrashType crash) : mCrash(crash) {}
+
+ void onData() {
+ switch (mCrash) {
+ case CrashType::ON_PLAIN: {
+ LOG_ALWAYS_FATAL("Expected crash, PLAIN.");
+ break;
+ }
+ case CrashType::ON_KNOWN_UID: {
+ if (IPCThreadState::self()->getCallingUid() == getuid()) {
+ LOG_ALWAYS_FATAL("Expected crash, KNOWN_UID.");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ Status setIntData(int /*input*/) override {
+ onData();
return Status::ok();
}
- Status setCharData(char16_t /*input*/) {
- LOG_ALWAYS_FATAL("Expected crash in setCharData");
+ Status setCharData(char16_t /*input*/) override {
+ onData();
return Status::ok();
}
- Status setBooleanData(bool /*input*/) {
- LOG_ALWAYS_FATAL("Expected crash in setBooleanData");
+ Status setBooleanData(bool /*input*/) override {
+ onData();
return Status::ok();
}
+
+ Status setService(const sp<ITestService>& service) override {
+ onData();
+ if (mCrash == CrashType::ON_BINDER && service != nullptr) {
+ LOG_ALWAYS_FATAL("Expected crash, BINDER.");
+ }
+ return Status::ok();
+ }
+
+private:
+ CrashType mCrash;
};
-} // namespace android
+
+CrashType gCrashType = CrashType::NONE;
+
+extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
+ if (*argc < 2) {
+ printf("You must specify at least one argument\n");
+ exit(0); // success because this is a crash test
+ }
+
+ std::string arg = std::string((*argv)[1]);
+
+ // ignore first argument, because we consume it
+ (*argv)[1] = (*argv[0]);
+ (*argc)--;
+ (*argv)++;
+
+ if (arg == "PLAIN") {
+ gCrashType = CrashType::ON_PLAIN;
+ } else if (arg == "KNOWN_UID") {
+ gCrashType = CrashType::ON_KNOWN_UID;
+ } else if (arg == "BINDER") {
+ gCrashType = CrashType::ON_BINDER;
+ } else {
+ printf("INVALID ARG\n");
+ exit(0); // success because this is a crash test
+ }
+
+ return 0;
+}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- auto service = sp<android::TestService>::make();
+ auto service = sp<TestService>::make(gCrashType);
fuzzService(service, FuzzedDataProvider(data, size));
return 0;
}
+
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh b/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
old mode 100644
new mode 100755
index cec52fd..e568035
--- a/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
@@ -27,16 +27,18 @@
exit 1
fi
-echo "INFO: Running fuzzer : test_service_fuzzer_should_crash"
+for CRASH_TYPE in PLAIN KNOWN_UID BINDER; do
+ echo "INFO: Running fuzzer : test_service_fuzzer_should_crash $CRASH_TYPE"
-./test_service_fuzzer_should_crash -max_total_time=30 &>${FUZZER_OUT}
+ ./test_service_fuzzer_should_crash "$CRASH_TYPE" -max_total_time=30 &>"$FUZZER_OUT"
-echo "INFO: Searching fuzzer output for expected crashes"
-if grep -q "Expected crash in set" ${FUZZER_OUT};
-then
- echo -e "${color_success}Success: Found expected crash. fuzzService test successful!"
-else
- echo -e "${color_failed}Failed: Unable to find successful fuzzing output from test_service_fuzzer_should_crash"
- echo "${color_reset}"
- exit 1
-fi
+ echo "INFO: Searching fuzzer output for expected crashes"
+ if grep -q "Expected crash, $CRASH_TYPE." "$FUZZER_OUT"
+ then
+ echo -e "${color_success}Success: Found expected crash. fuzzService test successful!"
+ else
+ echo -e "${color_failed}Failed: Unable to find successful fuzzing output from test_service_fuzzer_should_crash"
+ echo "${color_reset}"
+ exit 1
+ fi
+done
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
index 0ff65bf..07c681f 100644
--- a/services/gpuservice/OWNERS
+++ b/services/gpuservice/OWNERS
@@ -4,3 +4,4 @@
lfy@google.com
paulthomson@google.com
pbaiget@google.com
+kocdemir@google.com