Skip to content

Commit 97eba08

Browse files
Merge "Add support for injecting RPC binder accessors to libbinder" into main am: d53d074
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/3212539 Change-Id: I9c71a99dbd02ca34b9c9f2f8f5b5f295f636740c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
2 parents 08aa6b5 + d53d074 commit 97eba08

9 files changed

Lines changed: 567 additions & 27 deletions

File tree

libs/binder/BackendUnifiedServiceManager.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,31 +46,56 @@ binder::Status BackendUnifiedServiceManager::getService2(const ::std::string& na
4646
os::Service* _out) {
4747
os::Service service;
4848
binder::Status status = mTheRealServiceManager->getService2(name, &service);
49-
toBinderService(service, _out);
49+
if (status.isOk()) {
50+
return toBinderService(name, service, _out);
51+
}
5052
return status;
5153
}
5254

5355
binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
5456
os::Service* _out) {
5557
os::Service service;
5658
binder::Status status = mTheRealServiceManager->checkService(name, &service);
57-
toBinderService(service, _out);
59+
if (status.isOk()) {
60+
return toBinderService(name, service, _out);
61+
}
5862
return status;
5963
}
6064

61-
void BackendUnifiedServiceManager::toBinderService(const os::Service& in, os::Service* _out) {
65+
binder::Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
66+
const os::Service& in,
67+
os::Service* _out) {
6268
switch (in.getTag()) {
6369
case os::Service::Tag::binder: {
70+
if (in.get<os::Service::Tag::binder>() == nullptr) {
71+
// failed to find a service. Check to see if we have any local
72+
// injected Accessors for this service.
73+
os::Service accessor;
74+
binder::Status status = getInjectedAccessor(name, &accessor);
75+
if (!status.isOk()) {
76+
*_out = os::Service::make<os::Service::Tag::binder>(nullptr);
77+
return status;
78+
}
79+
if (accessor.getTag() == os::Service::Tag::accessor &&
80+
accessor.get<os::Service::Tag::accessor>() != nullptr) {
81+
ALOGI("Found local injected service for %s, will attempt to create connection",
82+
name.c_str());
83+
// Call this again using the accessor Service to get the real
84+
// service's binder into _out
85+
return toBinderService(name, accessor, _out);
86+
}
87+
}
88+
6489
*_out = in;
65-
break;
90+
return binder::Status::ok();
6691
}
6792
case os::Service::Tag::accessor: {
6893
sp<IBinder> accessorBinder = in.get<os::Service::Tag::accessor>();
6994
sp<IAccessor> accessor = interface_cast<IAccessor>(accessorBinder);
7095
if (accessor == nullptr) {
7196
ALOGE("Service#accessor doesn't have accessor. VM is maybe starting...");
7297
*_out = os::Service::make<os::Service::Tag::binder>(nullptr);
73-
break;
98+
return binder::Status::ok();
7499
}
75100
auto request = [=] {
76101
os::ParcelFileDescriptor fd;
@@ -83,10 +108,15 @@ void BackendUnifiedServiceManager::toBinderService(const os::Service& in, os::Se
83108
}
84109
};
85110
auto session = RpcSession::make();
86-
session->setupPreconnectedClient(base::unique_fd{}, request);
111+
status_t status = session->setupPreconnectedClient(base::unique_fd{}, request);
112+
if (status != OK) {
113+
ALOGE("Failed to set up preconnected binder RPC client: %s",
114+
statusToString(status).c_str());
115+
return binder::Status::fromStatusT(status);
116+
}
87117
session->setSessionSpecificRoot(accessorBinder);
88118
*_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
89-
break;
119+
return binder::Status::ok();
90120
}
91121
default: {
92122
LOG_ALWAYS_FATAL("Unknown service type: %d", in.getTag());
@@ -177,4 +207,4 @@ sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
177207
return gUnifiedServiceManager;
178208
}
179209

180-
} // namespace android
210+
} // namespace android

libs/binder/BackendUnifiedServiceManager.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ class BackendUnifiedServiceManager : public android::os::BnServiceManager {
5959

6060
private:
6161
sp<os::IServiceManager> mTheRealServiceManager;
62-
void toBinderService(const os::Service& in, os::Service* _out);
62+
binder::Status toBinderService(const ::std::string& name, const os::Service& in,
63+
os::Service* _out);
6364
};
6465

6566
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
6667

67-
} // namespace android
68+
android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service);
69+
70+
} // namespace android

libs/binder/IServiceManager.cpp

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include <sys/socket.h>
1718
#define LOG_TAG "ServiceManagerCppClient"
1819

1920
#include <binder/IServiceManager.h>
@@ -24,14 +25,19 @@
2425
#include <chrono>
2526
#include <condition_variable>
2627

28+
#include <FdTrigger.h>
29+
#include <RpcSocketAddress.h>
2730
#include <android-base/properties.h>
31+
#include <android/os/BnAccessor.h>
2832
#include <android/os/BnServiceCallback.h>
33+
#include <android/os/BnServiceManager.h>
2934
#include <android/os/IAccessor.h>
3035
#include <android/os/IServiceManager.h>
3136
#include <binder/IPCThreadState.h>
3237
#include <binder/Parcel.h>
38+
#include <binder/RpcSession.h>
3339
#include <utils/String8.h>
34-
40+
#include <variant>
3541
#ifndef __ANDROID_VNDK__
3642
#include <binder/IPermissionController.h>
3743
#endif
@@ -148,8 +154,141 @@ class CppBackendShim : public IServiceManager {
148154
}
149155
};
150156

157+
class AccessorProvider {
158+
public:
159+
AccessorProvider(RpcAccessorProvider&& provider) : mProvider(provider) {}
160+
sp<IBinder> provide(const String16& name) { return mProvider(name); }
161+
162+
private:
163+
AccessorProvider() = delete;
164+
165+
RpcAccessorProvider mProvider;
166+
};
167+
168+
class AccessorProviderEntry {
169+
public:
170+
AccessorProviderEntry(std::shared_ptr<AccessorProvider>&& provider) : mProvider(provider) {}
171+
std::shared_ptr<AccessorProvider> mProvider;
172+
173+
private:
174+
AccessorProviderEntry() = delete;
175+
};
176+
151177
[[clang::no_destroy]] static std::once_flag gSmOnce;
152178
[[clang::no_destroy]] static sp<IServiceManager> gDefaultServiceManager;
179+
[[clang::no_destroy]] static std::mutex gAccessorProvidersMutex;
180+
[[clang::no_destroy]] static std::vector<AccessorProviderEntry> gAccessorProviders;
181+
182+
class LocalAccessor : public android::os::BnAccessor {
183+
public:
184+
LocalAccessor(const String16& instance, RpcSocketAddressProvider&& connectionInfoProvider)
185+
: mInstance(instance), mConnectionInfoProvider(connectionInfoProvider) {
186+
LOG_ALWAYS_FATAL_IF(!mConnectionInfoProvider,
187+
"LocalAccessor object needs a valid connection info provider");
188+
}
189+
190+
~LocalAccessor() {
191+
if (mOnDelete) mOnDelete();
192+
}
193+
194+
::android::binder::Status addConnection(::android::os::ParcelFileDescriptor* outFd) {
195+
using android::os::IAccessor;
196+
sockaddr_storage addrStorage;
197+
std::unique_ptr<FdTrigger> trigger = FdTrigger::make();
198+
RpcTransportFd fd;
199+
status_t status =
200+
mConnectionInfoProvider(mInstance, reinterpret_cast<sockaddr*>(&addrStorage),
201+
sizeof(addrStorage));
202+
if (status != OK) {
203+
const std::string error = "The connection info provider was unable to provide "
204+
"connection info for instance " +
205+
std::string(String8(mInstance).c_str()) +
206+
" with status: " + statusToString(status);
207+
ALOGE("%s", error.c_str());
208+
return Status::fromServiceSpecificError(IAccessor::ERROR_CONNECTION_INFO_NOT_FOUND,
209+
error.c_str());
210+
}
211+
if (addrStorage.ss_family == AF_VSOCK) {
212+
sockaddr_vm* addr = reinterpret_cast<sockaddr_vm*>(&addrStorage);
213+
status = singleSocketConnection(VsockSocketAddress(addr->svm_cid, addr->svm_port),
214+
trigger, &fd);
215+
} else if (addrStorage.ss_family == AF_UNIX) {
216+
sockaddr_un* addr = reinterpret_cast<sockaddr_un*>(&addrStorage);
217+
status = singleSocketConnection(UnixSocketAddress(addr->sun_path), trigger, &fd);
218+
} else if (addrStorage.ss_family == AF_INET) {
219+
sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&addrStorage);
220+
status = singleSocketConnection(InetSocketAddress(reinterpret_cast<sockaddr*>(addr),
221+
sizeof(sockaddr_in),
222+
inet_ntoa(addr->sin_addr),
223+
ntohs(addr->sin_port)),
224+
trigger, &fd);
225+
} else {
226+
const std::string error =
227+
"Unsupported socket family type or the ConnectionInfoProvider failed to find a "
228+
"valid address. Family type: " +
229+
std::to_string(addrStorage.ss_family);
230+
ALOGE("%s", error.c_str());
231+
return Status::fromServiceSpecificError(IAccessor::ERROR_UNSUPPORTED_SOCKET_FAMILY,
232+
error.c_str());
233+
}
234+
if (status != OK) {
235+
const std::string error = "Failed to connect to socket for " +
236+
std::string(String8(mInstance).c_str()) +
237+
" with status: " + statusToString(status);
238+
ALOGE("%s", error.c_str());
239+
int err = 0;
240+
if (status == -EACCES) {
241+
err = IAccessor::ERROR_FAILED_TO_CONNECT_EACCES;
242+
} else {
243+
err = IAccessor::ERROR_FAILED_TO_CONNECT_TO_SOCKET;
244+
}
245+
return Status::fromServiceSpecificError(err, error.c_str());
246+
}
247+
*outFd = os::ParcelFileDescriptor(std::move(fd.fd));
248+
return Status::ok();
249+
}
250+
251+
::android::binder::Status getInstanceName(String16* instance) {
252+
*instance = mInstance;
253+
return Status::ok();
254+
}
255+
256+
private:
257+
LocalAccessor() = delete;
258+
String16 mInstance;
259+
RpcSocketAddressProvider mConnectionInfoProvider;
260+
std::function<void()> mOnDelete;
261+
};
262+
263+
android::binder::Status getInjectedAccessor(const std::string& name,
264+
android::os::Service* service) {
265+
std::vector<AccessorProviderEntry> copiedProviders;
266+
{
267+
std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
268+
copiedProviders.insert(copiedProviders.begin(), gAccessorProviders.begin(),
269+
gAccessorProviders.end());
270+
}
271+
272+
// Unlocked to call the providers. This requires the providers to be
273+
// threadsafe and not contain any references to objects that could be
274+
// deleted.
275+
for (const auto& provider : copiedProviders) {
276+
sp<IBinder> binder = provider.mProvider->provide(String16(name.c_str()));
277+
if (binder == nullptr) continue;
278+
status_t status = validateAccessor(String16(name.c_str()), binder);
279+
if (status != OK) {
280+
ALOGE("A provider returned a binder that is not an IAccessor for instance %s. Status: "
281+
"%s",
282+
name.c_str(), statusToString(status).c_str());
283+
return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
284+
}
285+
*service = os::Service::make<os::Service::Tag::accessor>(binder);
286+
return android::binder::Status::ok();
287+
}
288+
289+
*service = os::Service::make<os::Service::Tag::accessor>(nullptr);
290+
return android::binder::Status::ok();
291+
}
153292

154293
sp<IServiceManager> defaultServiceManager()
155294
{
@@ -172,6 +311,75 @@ void setDefaultServiceManager(const sp<IServiceManager>& sm) {
172311
}
173312
}
174313

314+
std::weak_ptr<AccessorProvider> addAccessorProvider(RpcAccessorProvider&& providerCallback) {
315+
std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
316+
std::shared_ptr<AccessorProvider> provider =
317+
std::make_shared<AccessorProvider>(std::move(providerCallback));
318+
gAccessorProviders.push_back(AccessorProviderEntry(std::move(provider)));
319+
320+
return provider;
321+
}
322+
323+
status_t removeAccessorProvider(std::weak_ptr<AccessorProvider> wProvider) {
324+
std::shared_ptr<AccessorProvider> provider = wProvider.lock();
325+
if (provider == nullptr) {
326+
ALOGE("The provider supplied to removeAccessorProvider has already been removed.");
327+
return NAME_NOT_FOUND;
328+
}
329+
std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
330+
size_t sizeBefore = gAccessorProviders.size();
331+
gAccessorProviders.erase(std::remove_if(gAccessorProviders.begin(), gAccessorProviders.end(),
332+
[&](AccessorProviderEntry entry) {
333+
return entry.mProvider == provider;
334+
}),
335+
gAccessorProviders.end());
336+
if (sizeBefore == gAccessorProviders.size()) {
337+
ALOGE("Failed to find an AccessorProvider for removeAccessorProvider");
338+
return NAME_NOT_FOUND;
339+
}
340+
341+
return OK;
342+
}
343+
344+
status_t validateAccessor(const String16& instance, const sp<IBinder>& binder) {
345+
if (binder == nullptr) {
346+
ALOGE("Binder is null");
347+
return BAD_VALUE;
348+
}
349+
sp<IAccessor> accessor = interface_cast<IAccessor>(binder);
350+
if (accessor == nullptr) {
351+
ALOGE("This binder for %s is not an IAccessor binder", String8(instance).c_str());
352+
return BAD_TYPE;
353+
}
354+
String16 reportedInstance;
355+
Status status = accessor->getInstanceName(&reportedInstance);
356+
if (!status.isOk()) {
357+
ALOGE("Failed to validate the binder being used to create a new ARpc_Accessor for %s with "
358+
"status: %s",
359+
String8(instance).c_str(), status.toString8().c_str());
360+
return NAME_NOT_FOUND;
361+
}
362+
if (reportedInstance != instance) {
363+
ALOGE("Instance %s doesn't match the Accessor's instance of %s", String8(instance).c_str(),
364+
String8(reportedInstance).c_str());
365+
return NAME_NOT_FOUND;
366+
}
367+
return OK;
368+
}
369+
370+
sp<IBinder> createAccessor(const String16& instance,
371+
RpcSocketAddressProvider&& connectionInfoProvider) {
372+
// Try to create a new accessor
373+
if (!connectionInfoProvider) {
374+
ALOGE("Could not find an Accessor for %s and no ConnectionInfoProvider provided to "
375+
"create a new one",
376+
String8(instance).c_str());
377+
return nullptr;
378+
}
379+
sp<IBinder> binder = sp<LocalAccessor>::make(instance, std::move(connectionInfoProvider));
380+
return binder;
381+
}
382+
175383
#if !defined(__ANDROID_VNDK__)
176384
// IPermissionController is not accessible to vendors
177385

libs/binder/RpcSession.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,21 @@ status_t RpcSession::setupSocketClient(const RpcSocketAddress& addr) {
589589
status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
590590
const std::vector<uint8_t>& sessionId,
591591
bool incoming) {
592+
RpcTransportFd transportFd;
593+
status_t status = singleSocketConnection(addr, mShutdownTrigger, &transportFd);
594+
if (status != OK) return status;
595+
596+
return initAndAddConnection(std::move(transportFd), sessionId, incoming);
597+
}
598+
599+
status_t singleSocketConnection(const RpcSocketAddress& addr,
600+
const std::unique_ptr<FdTrigger>& shutdownTrigger,
601+
RpcTransportFd* outFd) {
602+
LOG_ALWAYS_FATAL_IF(outFd == nullptr,
603+
"There is no reason to call this function without an outFd");
604+
LOG_ALWAYS_FATAL_IF(shutdownTrigger == nullptr,
605+
"FdTrigger argument is required so we don't get stuck in the connect call "
606+
"if the server process shuts down.");
592607
for (size_t tries = 0; tries < 5; tries++) {
593608
if (tries > 0) usleep(10000);
594609

@@ -620,7 +635,7 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
620635
if (connErrno == EAGAIN || connErrno == EINPROGRESS) {
621636
// For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
622637
// EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
623-
status_t pollStatus = mShutdownTrigger->triggerablePoll(transportFd, POLLOUT);
638+
status_t pollStatus = shutdownTrigger->triggerablePoll(transportFd, POLLOUT);
624639
if (pollStatus != OK) {
625640
ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
626641
statusToString(pollStatus).c_str());
@@ -654,7 +669,8 @@ status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
654669
LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(),
655670
transportFd.fd.get());
656671

657-
return initAndAddConnection(std::move(transportFd), sessionId, incoming);
672+
*outFd = std::move(transportFd);
673+
return OK;
658674
}
659675

660676
ALOGE("Ran out of retries to connect to %s", addr.toString().c_str());

0 commit comments

Comments
 (0)