Merge "libbinder: don't ignore sendDecStrong error"
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index fa63db5..677d6c7 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -60,6 +60,7 @@
MOCK_METHOD1(isDeclared, bool(const String16&));
MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&));
+ MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&));
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
};
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 6f08f74..cba7c4b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -22,9 +22,10 @@
#include <thread>
#include <vector>
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
+#include <android-base/parseint.h>
#include <android/hardware/tests/inheritance/1.0/IChild.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <hidl/HidlTransportSupport.h>
#include <vintf/parse_xml.h>
@@ -77,6 +78,13 @@
content += "\n";
content += option.c_str();
}
+ if (options.size() > 0) {
+ uint64_t len;
+ if (android::base::ParseUint(options[0], &len)) {
+ content += "\n";
+ content += std::string(len, 'X');
+ }
+ }
ssize_t written = write(fd, content.c_str(), content.size());
if (written != (ssize_t)content.size()) {
LOG(WARNING) << "SERVER(Child) debug writes " << written << " bytes < "
@@ -189,6 +197,16 @@
EXPECT_THAT(err.str(), HasSubstr("does not exist"));
}
+TEST_F(DebugTest, DebugLarge) {
+ EXPECT_EQ(0u, callMain(lshal, {
+ "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild/default", "10000"
+ }));
+ EXPECT_THAT(out.str(),
+ StrEq("android.hardware.tests.inheritance@1.0::IChild\n10000\n" +
+ std::string(10000, 'X')));
+ EXPECT_THAT(err.str(), IsEmpty());
+}
+
TEST_F(DebugTest, DebugParent) {
EXPECT_EQ(0u, callMain(lshal, {
"lshal", "debug", "android.hardware.tests.inheritance@1.0::IParent", "calling parent"
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 90db509..4e44ac7 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -121,6 +121,35 @@
return updatableViaApex;
}
+static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
+ AidlName aname;
+ if (!AidlName::fill(name, &aname)) return std::nullopt;
+
+ std::optional<std::string> ip;
+ std::optional<uint64_t> port;
+ forEachManifest([&](const ManifestWithDescription& mwd) {
+ mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+ if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
+ if (manifestInstance.package() != aname.package) return true;
+ if (manifestInstance.interface() != aname.iface) return true;
+ if (manifestInstance.instance() != aname.instance) return true;
+ ip = manifestInstance.ip();
+ port = manifestInstance.port();
+ return false; // break (libvintf uses opposite convention)
+ });
+ return false; // continue
+ });
+
+ if (ip.has_value() && port.has_value()) {
+ ConnectionInfo info;
+ info.ipAddress = *ip;
+ info.port = *port;
+ return std::make_optional<ConnectionInfo>(info);
+ } else {
+ return std::nullopt;
+ }
+}
+
static std::vector<std::string> getVintfInstances(const std::string& interface) {
size_t lastDot = interface.rfind('.');
if (lastDot == std::string::npos) {
@@ -437,6 +466,22 @@
return Status::ok();
}
+Status ServiceManager::getConnectionInfo(const std::string& name,
+ std::optional<ConnectionInfo>* outReturn) {
+ auto ctx = mAccess->getCallingContext();
+
+ if (!mAccess->canFind(ctx, name)) {
+ return Status::fromExceptionCode(Status::EX_SECURITY);
+ }
+
+ *outReturn = std::nullopt;
+
+#ifndef VENDORSERVICEMANAGER
+ *outReturn = getVintfConnectionInfo(name);
+#endif
+ return Status::ok();
+}
+
void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
ServiceCallbackMap::iterator* it,
bool* found) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 4f23c21..5e40319 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -24,6 +24,7 @@
namespace android {
+using os::ConnectionInfo;
using os::IClientCallback;
using os::IServiceCallback;
using os::ServiceDebugInfo;
@@ -48,6 +49,8 @@
binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
binder::Status updatableViaApex(const std::string& name,
std::optional<std::string>* outReturn) override;
+ binder::Status getConnectionInfo(const std::string& name,
+ std::optional<ConnectionInfo>* outReturn) override;
binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
const sp<IClientCallback>& cb) override;
binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6cb45ca..aff9e25 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -287,6 +287,7 @@
filegroup {
name: "libbinder_aidl",
srcs: [
+ "aidl/android/os/ConnectionInfo.aidl",
"aidl/android/os/IClientCallback.aidl",
"aidl/android/os/IServiceCallback.aidl",
"aidl/android/os/IServiceManager.aidl",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 6e318ea..aff9e0d 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -78,6 +78,7 @@
bool isDeclared(const String16& name) override;
Vector<String16> getDeclaredInstances(const String16& interface) override;
std::optional<String16> updatableViaApex(const String16& name) override;
+ std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
// for legacy ABI
const String16& getInterfaceDescriptor() const override {
@@ -426,6 +427,21 @@
return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
}
+std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnectionInfo(
+ const String16& name) {
+ std::optional<os::ConnectionInfo> connectionInfo;
+ if (Status status =
+ mTheRealServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo);
+ !status.isOk()) {
+ ALOGW("Failed to get ConnectionInfo for %s: %s", String8(name).c_str(),
+ status.toString8().c_str());
+ }
+ return connectionInfo.has_value()
+ ? std::make_optional<IServiceManager::ConnectionInfo>(
+ {connectionInfo->ipAddress, static_cast<unsigned int>(connectionInfo->port)})
+ : std::nullopt;
+}
+
#ifndef __ANDROID__
// ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
// The internal implementation of the AIDL interface android::os::IServiceManager calls into
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9f95167..6644187 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -233,7 +233,7 @@
ALOGE("null proxy");
} else {
if (proxy->isRpcBinder()) {
- ALOGE("Sending a socket binder over RPC is prohibited");
+ ALOGE("Sending a socket binder over kernel binder is prohibited");
return INVALID_OPERATION;
}
}
diff --git a/libs/binder/aidl/android/os/ConnectionInfo.aidl b/libs/binder/aidl/android/os/ConnectionInfo.aidl
new file mode 100644
index 0000000..160c9ea
--- /dev/null
+++ b/libs/binder/aidl/android/os/ConnectionInfo.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.os;
+
+/**
+ * Remote connection info associated with a declared service
+ * @hide
+ */
+parcelable ConnectionInfo {
+ /**
+ * IP address that the service is listening on.
+ */
+ @utf8InCpp String ipAddress;
+ /**
+ * Port number that the service is listening on. Actual value is an unsigned integer.
+ */
+ int port;
+}
+
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 75c4092..5880c0a 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -19,6 +19,7 @@
import android.os.IClientCallback;
import android.os.IServiceCallback;
import android.os.ServiceDebugInfo;
+import android.os.ConnectionInfo;
/**
* Basic interface for finding and publishing system services.
@@ -113,6 +114,11 @@
@nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name);
/**
+ * If connection info is available for the given instance, returns the ConnectionInfo
+ */
+ @nullable ConnectionInfo getConnectionInfo(@utf8InCpp String name);
+
+ /**
* Request a callback when the number of clients of the service changes.
* Used by LazyServiceRegistrar to dynamically stop services that have no clients.
*/
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index d152005..a48075d 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -15,11 +15,9 @@
*/
#pragma once
-
#include <binder/IInterface.h>
#include <utils/Vector.h>
#include <utils/String16.h>
-
#include <optional>
namespace android {
@@ -107,6 +105,16 @@
* this can be updated.
*/
virtual std::optional<String16> updatableViaApex(const String16& name) = 0;
+
+ /**
+ * If this instance has declared remote connection information, returns
+ * the ConnectionInfo.
+ */
+ struct ConnectionInfo {
+ std::string ipAddress;
+ unsigned int port;
+ };
+ virtual std::optional<ConnectionInfo> getConnectionInfo(const String16& name) = 0;
};
sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index a8ae441..8ed91a5 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -20,6 +20,7 @@
#include <android-base/logging.h>
using ::android::status_t;
+using ::android::statusToString;
using ::android::binder::Status;
AStatus* AStatus_newOk() {
@@ -126,7 +127,7 @@
return STATUS_UNKNOWN_ERROR;
default:
- LOG(WARNING) << __func__ << ": Unknown status_t (" << status
+ LOG(WARNING) << __func__ << ": Unknown status_t (" << statusToString(status)
<< ") pruned into STATUS_UNKNOWN_ERROR";
return STATUS_UNKNOWN_ERROR;
}
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 9811cdf..23e34aa 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -157,6 +157,11 @@
std::optional<std::string>* _aidl_return) override {
return mImpl->updatableViaApex(name, _aidl_return);
}
+ android::binder::Status getConnectionInfo(
+ const std::string& name,
+ std::optional<android::os::ConnectionInfo>* _aidl_return) override {
+ return mImpl->getConnectionInfo(name, _aidl_return);
+ }
android::binder::Status registerClientCallback(
const std::string&, const android::sp<android::IBinder>&,
const android::sp<android::os::IClientCallback>&) override {
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 23c1b14..71c0e86 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -206,7 +206,10 @@
cc_benchmark {
name: "binderRpcBenchmark",
- defaults: ["binder_test_defaults"],
+ defaults: [
+ "binder_test_defaults",
+ "libbinder_tls_shared_deps",
+ ],
host_supported: true,
target: {
darwin: {
@@ -216,6 +219,7 @@
srcs: [
"binderRpcBenchmark.cpp",
"IBinderRpcBenchmark.aidl",
+ "RpcAuthTesting.cpp",
],
shared_libs: [
"libbase",
@@ -223,6 +227,9 @@
"liblog",
"libutils",
],
+ static_libs: [
+ "libbinder_tls_static",
+ ],
}
cc_test {
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 55aa57b..0477d50 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -21,8 +21,14 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
+#include <binder/RpcCertificateFormat.h>
+#include <binder/RpcCertificateVerifier.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
+#include <binder/RpcTlsUtils.h>
+#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
+#include <openssl/ssl.h>
#include <thread>
@@ -31,6 +37,8 @@
#include <sys/types.h>
#include <unistd.h>
+#include "RpcAuthTesting.h"
+
using android::BBinder;
using android::defaultServiceManager;
using android::IBinder;
@@ -39,8 +47,14 @@
using android::IServiceManager;
using android::OK;
using android::ProcessState;
+using android::RpcAuthPreSigned;
+using android::RpcCertificateFormat;
+using android::RpcCertificateVerifier;
using android::RpcServer;
using android::RpcSession;
+using android::RpcTransportCtxFactory;
+using android::RpcTransportCtxFactoryRaw;
+using android::RpcTransportCtxFactoryTls;
using android::sp;
using android::status_t;
using android::statusToString;
@@ -65,15 +79,37 @@
enum Transport {
KERNEL,
RPC,
+ RPC_TLS,
};
static const std::initializer_list<int64_t> kTransportList = {
#ifdef __BIONIC__
Transport::KERNEL,
#endif
- Transport::RPC};
+ Transport::RPC,
+ Transport::RPC_TLS,
+};
+
+// Certificate validation happens during handshake and does not affect the result of benchmarks.
+// Skip certificate validation to simplify the setup process.
+class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
+public:
+ status_t verify(const SSL*, uint8_t*) override { return OK; }
+};
+
+std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
+ auto pkey = android::makeKeyPairForSelfSignedCert();
+ CHECK_NE(pkey.get(), nullptr);
+ auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
+ CHECK_NE(cert.get(), nullptr);
+
+ auto verifier = std::make_shared<RpcCertificateVerifierNoOp>();
+ auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
+ return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
+}
static sp<RpcSession> gSession = RpcSession::make();
+static sp<RpcSession> gSessionTls = RpcSession::make(makeFactoryTls());
#ifdef __BIONIC__
static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control");
static sp<IBinder> gKernelBinder;
@@ -88,6 +124,8 @@
#endif
case RPC:
return gSession->getRootObject();
+ case RPC_TLS:
+ return gSessionTls->getRootObject();
default:
LOG(FATAL) << "Unknown transport value: " << transport;
return nullptr;
@@ -169,26 +207,35 @@
}
BENCHMARK(BM_repeatBinder)->ArgsProduct({kTransportList});
+void forkRpcServer(const char* addr, const sp<RpcServer>& server) {
+ if (0 == fork()) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
+ server->setRootObject(sp<MyBinderRpcBenchmark>::make());
+ server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+ CHECK_EQ(OK, server->setupUnixDomainServer(addr));
+ server->join();
+ exit(1);
+ }
+}
+
+void setupClient(const sp<RpcSession>& session, const char* addr) {
+ status_t status;
+ for (size_t tries = 0; tries < 5; tries++) {
+ usleep(10000);
+ status = session->setupUnixDomainClient(addr);
+ if (status == OK) break;
+ }
+ CHECK_EQ(status, OK) << "Could not connect: " << addr << ": " << statusToString(status).c_str();
+}
+
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
- std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark";
- (void)unlink(addr.c_str());
-
std::cerr << "Tests suffixes:" << std::endl;
std::cerr << "\t.../" << Transport::KERNEL << " is KERNEL" << std::endl;
std::cerr << "\t.../" << Transport::RPC << " is RPC" << std::endl;
-
- if (0 == fork()) {
- prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
- sp<RpcServer> server = RpcServer::make();
- server->setRootObject(sp<MyBinderRpcBenchmark>::make());
- server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
- CHECK_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
- server->join();
- exit(1);
- }
+ std::cerr << "\t.../" << Transport::RPC_TLS << " is RPC with TLS" << std::endl;
#ifdef __BIONIC__
if (0 == fork()) {
@@ -207,13 +254,17 @@
CHECK_NE(nullptr, gKernelBinder.get());
#endif
- status_t status;
- for (size_t tries = 0; tries < 5; tries++) {
- usleep(10000);
- status = gSession->setupUnixDomainClient(addr.c_str());
- if (status == OK) break;
- }
- CHECK_EQ(status, OK) << "Could not connect: " << statusToString(status).c_str();
+ std::string tmp = getenv("TMPDIR") ?: "/tmp";
+
+ std::string addr = tmp + "/binderRpcBenchmark";
+ (void)unlink(addr.c_str());
+ forkRpcServer(addr.c_str(), RpcServer::make(RpcTransportCtxFactoryRaw::make()));
+ setupClient(gSession, addr.c_str());
+
+ std::string tlsAddr = tmp + "/binderRpcTlsBenchmark";
+ (void)unlink(tlsAddr.c_str());
+ forkRpcServer(tlsAddr.c_str(), RpcServer::make(makeFactoryTls()));
+ setupClient(gSessionTls, tlsAddr.c_str());
::benchmark::RunSpecifiedBenchmarks();
return 0;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 0e7e259..aad0162 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1053,7 +1053,7 @@
TEST_P(BinderRpc, OnewayStressTest) {
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
- constexpr size_t kNumCalls = 500;
+ constexpr size_t kNumCalls = 1000;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumServerThreads});
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 6c3b3d9..2398e1e 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -197,6 +197,14 @@
}
}
+TEST(BinderStability, ConnectionInfoRequiresManifestEntries) {
+ sp<IServiceManager> sm = android::defaultServiceManager();
+ sp<IBinder> systemBinder = BadStableBinder::system();
+ EXPECT_EQ(OK, sm->addService(String16("no.connection.foo"), systemBinder));
+ std::optional<android::IServiceManager::ConnectionInfo> connectionInfo;
+ connectionInfo = sm->getConnectionInfo(String16("no.connection.foo"));
+ EXPECT_EQ(connectionInfo, std::nullopt);
+}
TEST(BinderStability, CantCallVendorBinderInSystemContext) {
sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
auto server = interface_cast<IBinderStabilityTest>(serverBinder);
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 761e45c..9f0754b 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -78,4 +78,10 @@
return std::nullopt;
}
+std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo(
+ const String16& name) {
+ (void)name;
+ return std::nullopt;
+}
+
} // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index e26c21b..b1496ba 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -51,6 +51,8 @@
std::optional<String16> updatableViaApex(const String16& name) override;
+ std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
+
private:
std::map<String16, sp<IBinder>> mNameToService;
};