diff options
| -rw-r--r-- | libs/binder/BpBinder.cpp | 9 | ||||
| -rw-r--r-- | libs/binder/TEST_MAPPING | 3 | ||||
| -rw-r--r-- | libs/binder/include/binder/IBinder.h | 6 | ||||
| -rw-r--r-- | libs/binder/ndk/ibinder.cpp | 4 | ||||
| -rw-r--r-- | libs/binder/ndk/include_platform/android/binder_stability.h | 18 | ||||
| -rw-r--r-- | libs/binder/ndk/test/Android.bp | 28 | ||||
| -rw-r--r-- | libs/binder/ndk/test/AndroidTest.xml | 32 | ||||
| -rw-r--r-- | libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl | 19 | ||||
| -rw-r--r-- | libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp | 149 |
9 files changed, 264 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/TEST_MAPPING b/libs/binder/TEST_MAPPING index 136bdb0b86..8ae7e7a5ef 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -4,6 +4,9 @@ "name": "binderSafeInterfaceTest" }, { + "name": "binderVendorDoubleLoadTest" + }, + { "name": "binderDriverInterfaceTest" }, { 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 <android/binder_ibinder.h> #include "ibinder_internal.h" +#include <android/binder_stability.h> #include <android/binder_status.h> #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. */ 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<configuration description="Runs binderVendorDoubleLoadTest."> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-native" /> + + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="cleanup" value="true" /> + <option name="push" value="binderVendorDoubleLoadTest->/data/nativetest/vendor/binderVendorDoubleLoadTest" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/nativetest/vendor" /> + <option name="module-name" value="binderVendorDoubleLoadTest" /> + </test> +</configuration> + 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 <BnBinderVendorDoubleLoadTest.h> +#include <aidl/BnBinderVendorDoubleLoadTest.h> +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/strings.h> +#include <android/binder_ibinder.h> +#include <android/binder_manager.h> +#include <android/binder_process.h> +#include <android/binder_stability.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> +#include <binder/Stability.h> +#include <binder/Status.h> +#include <gtest/gtest.h> + +#include <sys/prctl.h> + +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<String16> services = defaultServiceManager()->listServices(); + EXPECT_TRUE(services.empty()); +} + +TEST(DoubleBinder, VendorCppCantRegisterService) { + sp<CppServer> 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<IBinder> 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> ndkServer = SharedRefBase::make<NdkServer>(); + 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<aidl::IBinderVendorDoubleLoadTest> 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> ndkServer = SharedRefBase::make<NdkServer>(); + 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> ndkServer = SharedRefBase::make<NdkServer>(); + AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str()); + + return RUN_ALL_TESTS(); +} |