Loading libs/binder/tests/Android.bp +0 −1 Original line number Original line Diff line number Diff line Loading @@ -142,7 +142,6 @@ aidl_interface { name: "binderStabilityTestIface", name: "binderStabilityTestIface", srcs: [ srcs: [ "IBinderStabilityTest.aidl", "IBinderStabilityTest.aidl", "IBinderStabilityTestSub.aidl", ], ], } } Loading libs/binder/tests/IBinderStabilityTest.aidl +6 −8 Original line number Original line Diff line number Diff line Loading @@ -14,34 +14,32 @@ * limitations under the License. * limitations under the License. */ */ import IBinderStabilityTestSub; // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! interface IBinderStabilityTest { interface IBinderStabilityTest { // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! void sendBinder(IBinderStabilityTestSub binder); void sendBinder(IBinder binder); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! void sendAndCallBinder(IBinderStabilityTestSub binder); void sendAndCallBinder(IBinder binder); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnNoStabilityBinder(); IBinder returnNoStabilityBinder(); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnLocalStabilityBinder(); IBinder returnLocalStabilityBinder(); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnVintfStabilityBinder(); IBinder returnVintfStabilityBinder(); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnVendorStabilityBinder(); IBinder returnVendorStabilityBinder(); } } // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! Loading libs/binder/tests/IBinderStabilityTestSub.aidldeleted 100644 → 0 +0 −19 Original line number Original line Diff line number Diff line /* * 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. */ interface IBinderStabilityTestSub { void userDefinedTransaction(); } libs/binder/tests/binderStabilityTest.cpp +145 −105 Original line number Original line Diff line number Diff line Loading @@ -26,9 +26,7 @@ #include <sys/prctl.h> #include <sys/prctl.h> #include "aidl/BnBinderStabilityTestSub.h" #include "aidl/BnBinderStabilityTest.h" #include "aidl/BnBinderStabilityTest.h" #include "BnBinderStabilityTestSub.h" #include "BnBinderStabilityTest.h" #include "BnBinderStabilityTest.h" using namespace android; using namespace android; Loading @@ -36,167 +34,217 @@ using namespace ndk; using android::binder::Status; using android::binder::Status; using android::internal::Stability; // for testing only! using android::internal::Stability; // for testing only! const String16 kNoStabilityServer = String16("binder_stability_test_service_low"); const String16 kSystemStabilityServer = String16("binder_stability_test_service_system"); const String16 kCompilationUnitServer = String16("binder_stability_test_service_compl"); const String16 kVintfServer = String16("binder_stability_test_service_vintf"); const String16 kCompilationUnitNdkServer = String16("binder_stability_test_service_compl"); // This is handwritten so that we can test different stability levels w/o having the AIDL // compiler assign them. Hand-writing binder interfaces is considered a bad practice class BadStabilityTestSub : public BnBinderStabilityTestSub { // sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD! class BadStableBinder : public BBinder { public: public: Status userDefinedTransaction() { static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION; return Status::ok(); static String16 kDescriptor; bool gotUserTransaction = false; static status_t doUserTransaction(const sp<IBinder>& binder) { Parcel data, reply; data.writeInterfaceToken(kDescriptor); return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/); } status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override { if (code == USER_TRANSACTION) { // not interested in this kind of stability. Make sure // we have a test failure LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor)); gotUserTransaction = true; ALOGE("binder stability: Got user transaction"); return OK; } return BBinder::onTransact(code, data, reply, flags); } } static sp<IBinderStabilityTestSub> system() { static sp<BadStableBinder> undef() { sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub(); sp<BadStableBinder> iface = new BadStableBinder(); // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS? // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS Stability::markCompilationUnit(iface.get()); // <- BAD, NO! DO NOT COPY return iface; return iface; } } static sp<IBinderStabilityTestSub> vintf() { static sp<BadStableBinder> system() { sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub(); sp<BadStableBinder> iface = new BadStableBinder(); // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS? Stability::markCompilationUnit(iface.get()); // <- for test only // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS Stability::markVintf(iface.get()); // <- BAD, NO! DO NOT COPY return iface; return iface; } } static sp<IBinderStabilityTestSub> vendor() { static sp<BadStableBinder> vintf() { sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub(); sp<BadStableBinder> iface = new BadStableBinder(); // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS? Stability::markVintf(iface.get()); // <- for test only // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS return iface; Stability::markVndk(iface.get()); // <- BAD, NO! DO NOT COPY } static sp<BadStableBinder> vendor() { sp<BadStableBinder> iface = new BadStableBinder(); Stability::markVndk(iface.get()); // <- for test only return iface; return iface; } } }; }; String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test"); // NO! NO! NO! Do not even think of doing something like this! // NO! NO! NO! Do not even think of doing something like this! // This is for testing! If a class like this was actually used in production, // This is for testing! If a class like this was actually used in production, // it would ruin everything! // it would ruin everything! class BadStabilityTester : public BnBinderStabilityTest { class MyBinderStabilityTest : public BnBinderStabilityTest { public: public: Status sendBinder(const sp<IBinderStabilityTestSub>& /*binder*/) override { Status sendBinder(const sp<IBinder>& /*binder*/) override { return Status::ok(); return Status::ok(); } } Status sendAndCallBinder(const sp<IBinderStabilityTestSub>& binder) override { Status sendAndCallBinder(const sp<IBinder>& binder) override { Stability::debugLogStability("sendAndCallBinder got binder", IInterface::asBinder(binder)); Stability::debugLogStability("sendAndCallBinder got binder", binder); return binder->userDefinedTransaction(); return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder)); } } Status returnNoStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = new BadStabilityTestSub(); *_aidl_return = BadStableBinder::undef(); return Status::ok(); return Status::ok(); } } Status returnLocalStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = BadStabilityTestSub::system(); *_aidl_return = BadStableBinder::system(); return Status::ok(); return Status::ok(); } } Status returnVintfStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = BadStabilityTestSub::vintf(); *_aidl_return = BadStableBinder::vintf(); return Status::ok(); return Status::ok(); } } Status returnVendorStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = BadStabilityTestSub::vendor(); *_aidl_return = BadStableBinder::vendor(); return Status::ok(); return Status::ok(); } } }; }; void checkSystemStabilityBinder(const sp<IBinderStabilityTest>& complServer) { TEST(BinderStability, CantCallVendorBinderInSystemContext) { EXPECT_TRUE(complServer->sendBinder(new BadStabilityTestSub()).isOk()); sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer); EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::system()).isOk()); auto server = interface_cast<IBinderStabilityTest>(serverBinder); EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vintf()).isOk()); EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vendor()).isOk()); ASSERT_NE(nullptr, server.get()); ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder()); EXPECT_TRUE(complServer->sendAndCallBinder(new BadStabilityTestSub()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk()); EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::system()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk()); EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::vintf()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk()); { sp<BadStableBinder> binder = BadStableBinder::undef(); EXPECT_TRUE(server->sendAndCallBinder(binder).isOk()); EXPECT_TRUE(binder->gotUserTransaction); } { sp<BadStableBinder> binder = BadStableBinder::system(); EXPECT_TRUE(server->sendAndCallBinder(binder).isOk()); EXPECT_TRUE(binder->gotUserTransaction); } { sp<BadStableBinder> binder = BadStableBinder::vintf(); EXPECT_TRUE(server->sendAndCallBinder(binder).isOk()); EXPECT_TRUE(binder->gotUserTransaction); } { // !!! user-defined transaction may not be stable for remote server !!! // !!! user-defined transaction may not be stable for remote server !!! EXPECT_FALSE(complServer->sendAndCallBinder(BadStabilityTestSub::vendor()).isOk()); // !!! so, it does not work !!! sp<BadStableBinder> binder = BadStableBinder::vendor(); EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode()); EXPECT_FALSE(binder->gotUserTransaction); } sp<IBinderStabilityTestSub> out; sp<IBinder> out; EXPECT_TRUE(complServer->returnNoStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); EXPECT_TRUE(out->userDefinedTransaction().isOk()); EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out)); EXPECT_TRUE(complServer->returnLocalStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); EXPECT_TRUE(out->userDefinedTransaction().isOk()); EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out)); EXPECT_TRUE(complServer->returnVintfStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); EXPECT_TRUE(out->userDefinedTransaction().isOk()); EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out)); EXPECT_TRUE(complServer->returnVendorStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); // !!! libbinder-defined transaction works !!! // !!! libbinder-defined transaction works !!! EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); // !!! user-defined transaction may not be stable !!! // !!! user-defined transaction may not be stable !!! EXPECT_FALSE(out->userDefinedTransaction().isOk()); // !!! so, it does not work !!! EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out)); } } TEST(BinderStability, RemoteNoStabilityServer) { // This is handwritten so that we can test different stability levels w/o having the AIDL sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kNoStabilityServer); // compiler assign them. Hand-writing binder interfaces is considered a bad practice auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder); // sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD! ASSERT_NE(nullptr, remoteServer.get()); struct NdkBinderStable_DataClass { ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder()); bool gotUserTransaction = false; }; checkSystemStabilityBinder(remoteServer); void* NdkBadStableBinder_Class_onCreate(void* args) { LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args"); return static_cast<void*>(new NdkBinderStable_DataClass); } } void NdkBadStableBinder_Class_onDestroy(void* userData) { TEST(BinderStability, RemoteLowStabilityServer) { delete static_cast<NdkBinderStable_DataClass*>(userData); sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kCompilationUnitServer); auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder); ASSERT_NE(nullptr, remoteServer.get()); ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder()); checkSystemStabilityBinder(remoteServer); } } NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) { LOG_ALWAYS_FATAL_IF(binder == nullptr); void* userData = AIBinder_getUserData(binder); LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?"); TEST(BinderStability, RemoteVintfServer) { return static_cast<NdkBinderStable_DataClass*>(userData); sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kVintfServer); } auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder); binder_status_t NdkBadStableBinder_Class_onTransact( AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) { ASSERT_NE(nullptr, remoteServer.get()); ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder()); checkSystemStabilityBinder(remoteServer); if (code == BadStableBinder::USER_TRANSACTION) { ALOGE("ndk binder stability: Got user transaction"); NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true; return STATUS_OK; } } class NdkBadStabilityTestSub : public aidl::BnBinderStabilityTestSub { return STATUS_UNKNOWN_TRANSACTION; ScopedAStatus userDefinedTransaction() { return ScopedAStatus::ok(); } } }; static AIBinder_Class* kNdkBadStableBinder = AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(), NdkBadStableBinder_Class_onCreate, NdkBadStableBinder_Class_onDestroy, NdkBadStableBinder_Class_onTransact); // for testing only to get around __ANDROID_VNDK__ guard. // for testing only to get around __ANDROID_VNDK__ guard. extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY TEST(BinderStability, NdkClientOfRemoteServer) { TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) { SpAIBinder binder = SpAIBinder(AServiceManager_getService( SpAIBinder binder = SpAIBinder(AServiceManager_getService( String8(kCompilationUnitServer).c_str())); String8(kSystemStabilityServer).c_str())); std::shared_ptr<aidl::IBinderStabilityTest> remoteServer = std::shared_ptr<aidl::IBinderStabilityTest> remoteServer = aidl::IBinderStabilityTest::fromBinder(binder); aidl::IBinderStabilityTest::fromBinder(binder); ASSERT_NE(nullptr, remoteServer.get()); ASSERT_NE(nullptr, remoteServer.get()); std::shared_ptr<aidl::IBinderStabilityTestSub> vendor = SharedRefBase::make<NdkBadStabilityTestSub>(); SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/)); EXPECT_TRUE(remoteServer->sendBinder(comp).isOk()); // TODO: not ideal: binder must be held once it is marked EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk()); SpAIBinder vendorBinder = vendor->asBinder(); EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction); AIBinder_markVendorStability(vendorBinder.get()); SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/)); AIBinder_markVendorStability(vendor.get()); EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk()); EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk()); EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk()); EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk()); EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction); } } class MarksStabilityInConstructor : public BBinder { class MarksStabilityInConstructor : public BBinder { Loading Loading @@ -234,16 +282,8 @@ int main(int argc, char** argv) { // child process // child process prctl(PR_SET_PDEATHSIG, SIGHUP); prctl(PR_SET_PDEATHSIG, SIGHUP); sp<IBinder> noStability = new BadStabilityTester; sp<IBinder> server = new MyBinderStabilityTest; android::defaultServiceManager()->addService(kNoStabilityServer, noStability); android::defaultServiceManager()->addService(kSystemStabilityServer, server); sp<IBinder> compil = new BadStabilityTester; Stability::markCompilationUnit(compil.get()); android::defaultServiceManager()->addService(kCompilationUnitServer, compil); sp<IBinder> vintf = new BadStabilityTester; Stability::markVintf(vintf.get()); android::defaultServiceManager()->addService(kVintfServer, vintf); IPCThreadState::self()->joinThreadPool(true); IPCThreadState::self()->joinThreadPool(true); exit(1); // should not reach exit(1); // should not reach Loading Loading
libs/binder/tests/Android.bp +0 −1 Original line number Original line Diff line number Diff line Loading @@ -142,7 +142,6 @@ aidl_interface { name: "binderStabilityTestIface", name: "binderStabilityTestIface", srcs: [ srcs: [ "IBinderStabilityTest.aidl", "IBinderStabilityTest.aidl", "IBinderStabilityTestSub.aidl", ], ], } } Loading
libs/binder/tests/IBinderStabilityTest.aidl +6 −8 Original line number Original line Diff line number Diff line Loading @@ -14,34 +14,32 @@ * limitations under the License. * limitations under the License. */ */ import IBinderStabilityTestSub; // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! interface IBinderStabilityTest { interface IBinderStabilityTest { // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! void sendBinder(IBinderStabilityTestSub binder); void sendBinder(IBinder binder); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! void sendAndCallBinder(IBinderStabilityTestSub binder); void sendAndCallBinder(IBinder binder); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnNoStabilityBinder(); IBinder returnNoStabilityBinder(); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnLocalStabilityBinder(); IBinder returnLocalStabilityBinder(); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnVintfStabilityBinder(); IBinder returnVintfStabilityBinder(); // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! IBinderStabilityTestSub returnVendorStabilityBinder(); IBinder returnVendorStabilityBinder(); } } // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS! // THIS IS ONLY FOR TESTING! // THIS IS ONLY FOR TESTING! Loading
libs/binder/tests/IBinderStabilityTestSub.aidldeleted 100644 → 0 +0 −19 Original line number Original line Diff line number Diff line /* * 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. */ interface IBinderStabilityTestSub { void userDefinedTransaction(); }
libs/binder/tests/binderStabilityTest.cpp +145 −105 Original line number Original line Diff line number Diff line Loading @@ -26,9 +26,7 @@ #include <sys/prctl.h> #include <sys/prctl.h> #include "aidl/BnBinderStabilityTestSub.h" #include "aidl/BnBinderStabilityTest.h" #include "aidl/BnBinderStabilityTest.h" #include "BnBinderStabilityTestSub.h" #include "BnBinderStabilityTest.h" #include "BnBinderStabilityTest.h" using namespace android; using namespace android; Loading @@ -36,167 +34,217 @@ using namespace ndk; using android::binder::Status; using android::binder::Status; using android::internal::Stability; // for testing only! using android::internal::Stability; // for testing only! const String16 kNoStabilityServer = String16("binder_stability_test_service_low"); const String16 kSystemStabilityServer = String16("binder_stability_test_service_system"); const String16 kCompilationUnitServer = String16("binder_stability_test_service_compl"); const String16 kVintfServer = String16("binder_stability_test_service_vintf"); const String16 kCompilationUnitNdkServer = String16("binder_stability_test_service_compl"); // This is handwritten so that we can test different stability levels w/o having the AIDL // compiler assign them. Hand-writing binder interfaces is considered a bad practice class BadStabilityTestSub : public BnBinderStabilityTestSub { // sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD! class BadStableBinder : public BBinder { public: public: Status userDefinedTransaction() { static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION; return Status::ok(); static String16 kDescriptor; bool gotUserTransaction = false; static status_t doUserTransaction(const sp<IBinder>& binder) { Parcel data, reply; data.writeInterfaceToken(kDescriptor); return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/); } status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override { if (code == USER_TRANSACTION) { // not interested in this kind of stability. Make sure // we have a test failure LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor)); gotUserTransaction = true; ALOGE("binder stability: Got user transaction"); return OK; } return BBinder::onTransact(code, data, reply, flags); } } static sp<IBinderStabilityTestSub> system() { static sp<BadStableBinder> undef() { sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub(); sp<BadStableBinder> iface = new BadStableBinder(); // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS? // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS Stability::markCompilationUnit(iface.get()); // <- BAD, NO! DO NOT COPY return iface; return iface; } } static sp<IBinderStabilityTestSub> vintf() { static sp<BadStableBinder> system() { sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub(); sp<BadStableBinder> iface = new BadStableBinder(); // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS? Stability::markCompilationUnit(iface.get()); // <- for test only // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS Stability::markVintf(iface.get()); // <- BAD, NO! DO NOT COPY return iface; return iface; } } static sp<IBinderStabilityTestSub> vendor() { static sp<BadStableBinder> vintf() { sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub(); sp<BadStableBinder> iface = new BadStableBinder(); // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS? Stability::markVintf(iface.get()); // <- for test only // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS return iface; Stability::markVndk(iface.get()); // <- BAD, NO! DO NOT COPY } static sp<BadStableBinder> vendor() { sp<BadStableBinder> iface = new BadStableBinder(); Stability::markVndk(iface.get()); // <- for test only return iface; return iface; } } }; }; String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test"); // NO! NO! NO! Do not even think of doing something like this! // NO! NO! NO! Do not even think of doing something like this! // This is for testing! If a class like this was actually used in production, // This is for testing! If a class like this was actually used in production, // it would ruin everything! // it would ruin everything! class BadStabilityTester : public BnBinderStabilityTest { class MyBinderStabilityTest : public BnBinderStabilityTest { public: public: Status sendBinder(const sp<IBinderStabilityTestSub>& /*binder*/) override { Status sendBinder(const sp<IBinder>& /*binder*/) override { return Status::ok(); return Status::ok(); } } Status sendAndCallBinder(const sp<IBinderStabilityTestSub>& binder) override { Status sendAndCallBinder(const sp<IBinder>& binder) override { Stability::debugLogStability("sendAndCallBinder got binder", IInterface::asBinder(binder)); Stability::debugLogStability("sendAndCallBinder got binder", binder); return binder->userDefinedTransaction(); return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder)); } } Status returnNoStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = new BadStabilityTestSub(); *_aidl_return = BadStableBinder::undef(); return Status::ok(); return Status::ok(); } } Status returnLocalStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = BadStabilityTestSub::system(); *_aidl_return = BadStableBinder::system(); return Status::ok(); return Status::ok(); } } Status returnVintfStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = BadStabilityTestSub::vintf(); *_aidl_return = BadStableBinder::vintf(); return Status::ok(); return Status::ok(); } } Status returnVendorStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override { Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override { *_aidl_return = BadStabilityTestSub::vendor(); *_aidl_return = BadStableBinder::vendor(); return Status::ok(); return Status::ok(); } } }; }; void checkSystemStabilityBinder(const sp<IBinderStabilityTest>& complServer) { TEST(BinderStability, CantCallVendorBinderInSystemContext) { EXPECT_TRUE(complServer->sendBinder(new BadStabilityTestSub()).isOk()); sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer); EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::system()).isOk()); auto server = interface_cast<IBinderStabilityTest>(serverBinder); EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vintf()).isOk()); EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vendor()).isOk()); ASSERT_NE(nullptr, server.get()); ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder()); EXPECT_TRUE(complServer->sendAndCallBinder(new BadStabilityTestSub()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk()); EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::system()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk()); EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::vintf()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk()); EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk()); { sp<BadStableBinder> binder = BadStableBinder::undef(); EXPECT_TRUE(server->sendAndCallBinder(binder).isOk()); EXPECT_TRUE(binder->gotUserTransaction); } { sp<BadStableBinder> binder = BadStableBinder::system(); EXPECT_TRUE(server->sendAndCallBinder(binder).isOk()); EXPECT_TRUE(binder->gotUserTransaction); } { sp<BadStableBinder> binder = BadStableBinder::vintf(); EXPECT_TRUE(server->sendAndCallBinder(binder).isOk()); EXPECT_TRUE(binder->gotUserTransaction); } { // !!! user-defined transaction may not be stable for remote server !!! // !!! user-defined transaction may not be stable for remote server !!! EXPECT_FALSE(complServer->sendAndCallBinder(BadStabilityTestSub::vendor()).isOk()); // !!! so, it does not work !!! sp<BadStableBinder> binder = BadStableBinder::vendor(); EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode()); EXPECT_FALSE(binder->gotUserTransaction); } sp<IBinderStabilityTestSub> out; sp<IBinder> out; EXPECT_TRUE(complServer->returnNoStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); EXPECT_TRUE(out->userDefinedTransaction().isOk()); EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out)); EXPECT_TRUE(complServer->returnLocalStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); EXPECT_TRUE(out->userDefinedTransaction().isOk()); EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out)); EXPECT_TRUE(complServer->returnVintfStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); EXPECT_TRUE(out->userDefinedTransaction().isOk()); EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out)); EXPECT_TRUE(complServer->returnVendorStabilityBinder(&out).isOk()); EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk()); ASSERT_NE(nullptr, out.get()); ASSERT_NE(nullptr, out.get()); // !!! libbinder-defined transaction works !!! // !!! libbinder-defined transaction works !!! EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder()); EXPECT_EQ(OK, out->pingBinder()); // !!! user-defined transaction may not be stable !!! // !!! user-defined transaction may not be stable !!! EXPECT_FALSE(out->userDefinedTransaction().isOk()); // !!! so, it does not work !!! EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out)); } } TEST(BinderStability, RemoteNoStabilityServer) { // This is handwritten so that we can test different stability levels w/o having the AIDL sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kNoStabilityServer); // compiler assign them. Hand-writing binder interfaces is considered a bad practice auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder); // sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD! ASSERT_NE(nullptr, remoteServer.get()); struct NdkBinderStable_DataClass { ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder()); bool gotUserTransaction = false; }; checkSystemStabilityBinder(remoteServer); void* NdkBadStableBinder_Class_onCreate(void* args) { LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args"); return static_cast<void*>(new NdkBinderStable_DataClass); } } void NdkBadStableBinder_Class_onDestroy(void* userData) { TEST(BinderStability, RemoteLowStabilityServer) { delete static_cast<NdkBinderStable_DataClass*>(userData); sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kCompilationUnitServer); auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder); ASSERT_NE(nullptr, remoteServer.get()); ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder()); checkSystemStabilityBinder(remoteServer); } } NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) { LOG_ALWAYS_FATAL_IF(binder == nullptr); void* userData = AIBinder_getUserData(binder); LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?"); TEST(BinderStability, RemoteVintfServer) { return static_cast<NdkBinderStable_DataClass*>(userData); sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kVintfServer); } auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder); binder_status_t NdkBadStableBinder_Class_onTransact( AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) { ASSERT_NE(nullptr, remoteServer.get()); ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder()); checkSystemStabilityBinder(remoteServer); if (code == BadStableBinder::USER_TRANSACTION) { ALOGE("ndk binder stability: Got user transaction"); NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true; return STATUS_OK; } } class NdkBadStabilityTestSub : public aidl::BnBinderStabilityTestSub { return STATUS_UNKNOWN_TRANSACTION; ScopedAStatus userDefinedTransaction() { return ScopedAStatus::ok(); } } }; static AIBinder_Class* kNdkBadStableBinder = AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(), NdkBadStableBinder_Class_onCreate, NdkBadStableBinder_Class_onDestroy, NdkBadStableBinder_Class_onTransact); // for testing only to get around __ANDROID_VNDK__ guard. // for testing only to get around __ANDROID_VNDK__ guard. extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY TEST(BinderStability, NdkClientOfRemoteServer) { TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) { SpAIBinder binder = SpAIBinder(AServiceManager_getService( SpAIBinder binder = SpAIBinder(AServiceManager_getService( String8(kCompilationUnitServer).c_str())); String8(kSystemStabilityServer).c_str())); std::shared_ptr<aidl::IBinderStabilityTest> remoteServer = std::shared_ptr<aidl::IBinderStabilityTest> remoteServer = aidl::IBinderStabilityTest::fromBinder(binder); aidl::IBinderStabilityTest::fromBinder(binder); ASSERT_NE(nullptr, remoteServer.get()); ASSERT_NE(nullptr, remoteServer.get()); std::shared_ptr<aidl::IBinderStabilityTestSub> vendor = SharedRefBase::make<NdkBadStabilityTestSub>(); SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/)); EXPECT_TRUE(remoteServer->sendBinder(comp).isOk()); // TODO: not ideal: binder must be held once it is marked EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk()); SpAIBinder vendorBinder = vendor->asBinder(); EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction); AIBinder_markVendorStability(vendorBinder.get()); SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/)); AIBinder_markVendorStability(vendor.get()); EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk()); EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk()); EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk()); EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk()); EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction); } } class MarksStabilityInConstructor : public BBinder { class MarksStabilityInConstructor : public BBinder { Loading Loading @@ -234,16 +282,8 @@ int main(int argc, char** argv) { // child process // child process prctl(PR_SET_PDEATHSIG, SIGHUP); prctl(PR_SET_PDEATHSIG, SIGHUP); sp<IBinder> noStability = new BadStabilityTester; sp<IBinder> server = new MyBinderStabilityTest; android::defaultServiceManager()->addService(kNoStabilityServer, noStability); android::defaultServiceManager()->addService(kSystemStabilityServer, server); sp<IBinder> compil = new BadStabilityTester; Stability::markCompilationUnit(compil.get()); android::defaultServiceManager()->addService(kCompilationUnitServer, compil); sp<IBinder> vintf = new BadStabilityTester; Stability::markVintf(vintf.get()); android::defaultServiceManager()->addService(kVintfServer, vintf); IPCThreadState::self()->joinThreadPool(true); IPCThreadState::self()->joinThreadPool(true); exit(1); // should not reach exit(1); // should not reach Loading