From d201734393d9954f50af51e058a085bf92fea83f Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 22 Jul 2019 14:30:11 -0700 Subject: Test double-loading libbinder. This is in preparation for the technical possibility of vendor using libbinder_ndk to communicate w/ Stable AIDL interfaces on system or for other possible usecases which may use double loaded libbinder. Bug: 136027762 Bug: 138450837 Test: atest binderVendorDoubleLoadTest Change-Id: I7b166ae08954283b378e1f18d2c44dcf70e698c5 --- libs/binder/TEST_MAPPING | 3 + libs/binder/ndk/test/Android.bp | 28 ++++ libs/binder/ndk/test/AndroidTest.xml | 32 +++++ .../ndk/test/IBinderVendorDoubleLoadTest.aidl | 19 +++ .../binder/ndk/test/binderVendorDoubleLoadTest.cpp | 149 +++++++++++++++++++++ 5 files changed, 231 insertions(+) create mode 100644 libs/binder/ndk/test/AndroidTest.xml create mode 100644 libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl create mode 100644 libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index 136bdb0b86..8ae7e7a5ef 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -3,6 +3,9 @@ { "name": "binderSafeInterfaceTest" }, + { + "name": "binderVendorDoubleLoadTest" + }, { "name": "binderDriverInterfaceTest" }, diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp index bb1fe2f8e3..1c5dba3736 100644 --- a/libs/binder/ndk/test/Android.bp +++ b/libs/binder/ndk/test/Android.bp @@ -67,3 +67,31 @@ cc_test { srcs: ["main_server.cpp"], gtest: false, } + +cc_test { + name: "binderVendorDoubleLoadTest", + vendor: true, + srcs: [ + "binderVendorDoubleLoadTest.cpp", + ], + static_libs: [ + "IBinderVendorDoubleLoadTest-cpp", + "IBinderVendorDoubleLoadTest-ndk_platform", + ], + shared_libs: [ + "libbase", + "libbinder", + "libbinder_ndk", + "libutils", + ], + test_suites: ["device-tests"], +} + +aidl_interface { + name: "IBinderVendorDoubleLoadTest", + // TODO(b/119771576): only vendor is needed + vendor_available: true, + srcs: [ + "IBinderVendorDoubleLoadTest.aidl", + ], +} diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/test/AndroidTest.xml new file mode 100644 index 0000000000..89646f7776 --- /dev/null +++ b/libs/binder/ndk/test/AndroidTest.xml @@ -0,0 +1,32 @@ + + + + + diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl new file mode 100644 index 0000000000..3a5bd9cc56 --- /dev/null +++ b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl @@ -0,0 +1,19 @@ +/* + * 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 IBinderVendorDoubleLoadTest { + @utf8InCpp String RepeatString(@utf8InCpp String toRepeat); +} diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp new file mode 100644 index 0000000000..f72dc36cfd --- /dev/null +++ b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp @@ -0,0 +1,149 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace android; +using ::android::base::EndsWith; +using ::android::base::GetProperty; +using ::android::base::Split; +using ::android::binder::Status; +using ::android::internal::Stability; +using ::ndk::ScopedAStatus; +using ::ndk::SharedRefBase; +using ::ndk::SpAIBinder; + +static const std::string kLocalNdkServerName = "NdkServer-local-IBinderVendorDoubleLoadTest"; +static const std::string kRemoteNdkServerName = "NdkServer-remote-IBinderVendorDoubleLoadTest"; + +class NdkServer : public aidl::BnBinderVendorDoubleLoadTest { + ScopedAStatus RepeatString(const std::string& in, std::string* out) override { + *out = in; + return ScopedAStatus::ok(); + } +}; +class CppServer : public BnBinderVendorDoubleLoadTest { + Status RepeatString(const std::string& in, std::string* out) override { + *out = in; + return Status::ok(); + } +}; + +TEST(DoubleBinder, VendorCppCantCallIntoSystem) { + Vector services = defaultServiceManager()->listServices(); + EXPECT_TRUE(services.empty()); +} + +TEST(DoubleBinder, VendorCppCantRegisterService) { + sp cppServer = new CppServer; + status_t status = defaultServiceManager()->addService(String16("anything"), cppServer); + EXPECT_EQ(EX_TRANSACTION_FAILED, status); +} + +TEST(DoubleBinder, CppVendorCantManuallyMarkVintfStability) { + // this test also implies that stability logic is turned on in vendor + ASSERT_DEATH( + { + sp binder = new CppServer(); + Stability::markVintf(binder.get()); + }, + "Should only mark known object."); +} + +TEST(DoubleBinder, NdkVendorCantManuallyMarkVintfStability) { + // this test also implies that stability logic is turned on in vendor + ASSERT_DEATH( + { + std::shared_ptr ndkServer = SharedRefBase::make(); + AIBinder_markVintfStability(ndkServer->asBinder().get()); + }, + "Should only mark known object."); +} + +TEST(DoubleBinder, CallIntoNdk) { + for (const std::string& serviceName : {kLocalNdkServerName, kRemoteNdkServerName}) { + SpAIBinder binder = SpAIBinder(AServiceManager_checkService(serviceName.c_str())); + ASSERT_NE(nullptr, binder.get()) << serviceName; + EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())) << serviceName; + + std::shared_ptr server = + aidl::IBinderVendorDoubleLoadTest::fromBinder(binder); + + ASSERT_NE(nullptr, server.get()) << serviceName; + + EXPECT_EQ(STATUS_OK, AIBinder_ping(server->asBinder().get())); + + std::string outString; + ScopedAStatus status = server->RepeatString("foo", &outString); + EXPECT_EQ(STATUS_OK, AStatus_getExceptionCode(status.get())) << serviceName; + EXPECT_EQ("foo", outString) << serviceName; + } +} + +void initDrivers() { + // Explicitly instantiated with the same driver that system would use. + // __ANDROID_VNDK__ right now uses /dev/vndbinder by default. + ProcessState::initWithDriver("/dev/binder"); + ProcessState::self()->startThreadPool(); + ABinderProcess_startThreadPool(); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + if (fork() == 0) { + // child process + + prctl(PR_SET_PDEATHSIG, SIGHUP); + + initDrivers(); + + // REMOTE SERVERS + std::shared_ptr ndkServer = SharedRefBase::make(); + CHECK(STATUS_OK == AServiceManager_addService(ndkServer->asBinder().get(), + kRemoteNdkServerName.c_str())); + + // OR sleep forever or whatever, it doesn't matter + IPCThreadState::self()->joinThreadPool(true); + exit(1); // should not reach + } + + sleep(1); + + initDrivers(); + + // LOCAL SERVERS + std::shared_ptr ndkServer = SharedRefBase::make(); + AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str()); + + return RUN_ALL_TESTS(); +} -- cgit v1.2.3-59-g8ed1b From 46b5fea67c2e65a65e28209ba657acd7e45d3462 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 15 Oct 2019 11:22:18 -0700 Subject: libbinder_ndk: fix vendor<->vendor transactions. Before, BpBinder was blocking these since kLocalStability was always vendor. Fixes: 142658240 Test: binderVendorDoubleLoadTest Change-Id: I898a76fc35ed6a15e783b53e925ec47877790b7c --- libs/binder/BpBinder.cpp | 9 +++++++-- libs/binder/include/binder/IBinder.h | 6 +++++- libs/binder/ndk/ibinder.cpp | 4 +++- .../ndk/include_platform/android/binder_stability.h | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 50c7053b13..238c9dcc7f 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -214,16 +214,21 @@ status_t BpBinder::transact( { // Once a binder has died, it will never come back to life. if (mAlive) { + bool privateVendor = flags & FLAG_PRIVATE_VENDOR; + // don't send userspace flags to the kernel + flags = flags & ~FLAG_PRIVATE_VENDOR; + // user transactions require a given stability level if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) { using android::internal::Stability; auto stability = Stability::get(this); + auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability; - if (CC_UNLIKELY(!Stability::check(stability, Stability::kLocalStability))) { + if (CC_UNLIKELY(!Stability::check(stability, required))) { ALOGE("Cannot do a user transaction on a %s binder in a %s context.", Stability::stabilityString(stability).c_str(), - Stability::stabilityString(Stability::kLocalStability).c_str()); + Stability::stabilityString(required).c_str()); return BAD_TYPE; } } diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h index 64f305274b..64604b74f0 100644 --- a/libs/binder/include/binder/IBinder.h +++ b/libs/binder/include/binder/IBinder.h @@ -62,7 +62,11 @@ public: DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'), // Corresponds to TF_ONE_WAY -- an asynchronous call. - FLAG_ONEWAY = 0x00000001 + FLAG_ONEWAY = 0x00000001, + + // Private userspace flag for transaction which is being requested from + // a vendor context. + FLAG_PRIVATE_VENDOR = 0x10000000, }; IBinder(); diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index b06ca86f57..e752c45d60 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -17,6 +17,7 @@ #include #include "ibinder_internal.h" +#include #include #include "parcel_internal.h" #include "status_internal.h" @@ -542,7 +543,8 @@ binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, APa return STATUS_UNKNOWN_TRANSACTION; } - if ((flags & ~FLAG_ONEWAY) != 0) { + constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY; + if ((flags & ~kAllFlags) != 0) { LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags; return STATUS_BAD_VALUE; } diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h index 924812e43d..2a4ded8691 100644 --- a/libs/binder/ndk/include_platform/android/binder_stability.h +++ b/libs/binder/ndk/include_platform/android/binder_stability.h @@ -20,9 +20,23 @@ __BEGIN_DECLS +/** + * Private addition to binder_flag_t. + */ +enum { + /** + * Indicates that this transaction is coupled w/ vendor.img + */ + FLAG_PRIVATE_VENDOR = 0x10000000, +}; + #if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \ (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)) +enum { + FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR, +}; + /** * This interface has the stability of the vendor image. */ @@ -35,6 +49,10 @@ static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) { #else // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && // !defined(__ANDROID_APEX__)) +enum { + FLAG_PRIVATE_LOCAL = 0, +}; + /** * This interface has the stability of the system image. */ -- cgit v1.2.3-59-g8ed1b