blob: eceff35e3ef8eefc381da84a91d4dbe2e158bccd [file] [log] [blame]
Andrei Homescu2a298012022-06-15 01:08:54 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <BinderRpcTestClientInfo.h>
20#include <BinderRpcTestServerConfig.h>
21#include <BinderRpcTestServerInfo.h>
22#include <BnBinderRpcCallback.h>
23#include <BnBinderRpcSession.h>
24#include <BnBinderRpcTest.h>
Andrei Homescu9d8adb12022-08-02 04:38:30 +000025#include <android-base/stringprintf.h>
26#include <binder/Binder.h>
27#include <binder/BpBinder.h>
28#include <binder/IPCThreadState.h>
29#include <binder/IServiceManager.h>
30#include <binder/RpcServer.h>
31#include <binder/RpcSession.h>
32#include <binder/RpcThreads.h>
33#include <binder/RpcTransport.h>
34#include <binder/RpcTransportRaw.h>
35#include <unistd.h>
36#include <cinttypes>
37#include <string>
38#include <vector>
39
40#ifndef __TRUSTY__
Andrei Homescu2a298012022-06-15 01:08:54 +000041#include <android-base/file.h>
42#include <android-base/logging.h>
43#include <android-base/properties.h>
44#include <android/binder_auto_utils.h>
45#include <android/binder_libbinder.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000046#include <binder/ProcessState.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000047#include <binder/RpcTlsTestUtils.h>
48#include <binder/RpcTlsUtils.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000049#include <binder/RpcTransportTls.h>
Andrei Homescu2a298012022-06-15 01:08:54 +000050
51#include <signal.h>
52
David Brazdil21c887c2022-09-23 12:25:18 +010053#include "../OS.h" // for testing UnixBootstrap clients
Andrei Homescu2a298012022-06-15 01:08:54 +000054#include "../RpcSocketAddress.h" // for testing preconnected clients
Andrei Homescu2a298012022-06-15 01:08:54 +000055#include "../vm_sockets.h" // for VMADDR_*
Andrei Homescu9d8adb12022-08-02 04:38:30 +000056#endif // __TRUSTY__
57
58#include "../BuildFlags.h"
59#include "../FdTrigger.h"
60#include "../RpcState.h" // for debugging
Andrei Homescu2a298012022-06-15 01:08:54 +000061#include "utils/Errors.h"
62
63namespace android {
64
65constexpr char kLocalInetAddress[] = "127.0.0.1";
66
67enum class RpcSecurity { RAW, TLS };
68
69static inline std::vector<RpcSecurity> RpcSecurityValues() {
70 return {RpcSecurity::RAW, RpcSecurity::TLS};
71}
72
Steven Moreland0884c552023-10-17 18:23:31 +000073static inline bool hasExperimentalRpc() {
74#ifdef __ANDROID__
75 return base::GetProperty("ro.build.version.codename", "") != "REL";
76#else
77 // TODO(b/305983144): restrict on other platforms
78 return true;
79#endif
80}
81
Andrei Homescu9d8adb12022-08-02 04:38:30 +000082static inline std::vector<uint32_t> testVersions() {
83 std::vector<uint32_t> versions;
84 for (size_t i = 0; i < RPC_WIRE_PROTOCOL_VERSION_NEXT; i++) {
85 versions.push_back(i);
86 }
Steven Moreland0884c552023-10-17 18:23:31 +000087 if (hasExperimentalRpc()) {
88 versions.push_back(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
89 }
Andrei Homescu9d8adb12022-08-02 04:38:30 +000090 return versions;
91}
92
93static inline std::string trustyIpcPort(uint32_t serverVersion) {
94 return base::StringPrintf("com.android.trusty.binderRpcTestService.V%" PRIu32, serverVersion);
95}
96
Andrei Homescu2a298012022-06-15 01:08:54 +000097enum class SocketType {
98 PRECONNECTED,
99 UNIX,
David Brazdil21c887c2022-09-23 12:25:18 +0100100 UNIX_BOOTSTRAP,
Alice Wang893a9912022-10-24 10:44:09 +0000101 UNIX_RAW,
Andrei Homescu2a298012022-06-15 01:08:54 +0000102 VSOCK,
103 INET,
Andrei Homescu68a55612022-08-02 01:25:15 +0000104 TIPC,
Andrei Homescu2a298012022-06-15 01:08:54 +0000105};
David Brazdil21c887c2022-09-23 12:25:18 +0100106
Andrei Homescu2a298012022-06-15 01:08:54 +0000107static inline std::string PrintToString(SocketType socketType) {
108 switch (socketType) {
109 case SocketType::PRECONNECTED:
110 return "preconnected_uds";
111 case SocketType::UNIX:
112 return "unix_domain_socket";
David Brazdil21c887c2022-09-23 12:25:18 +0100113 case SocketType::UNIX_BOOTSTRAP:
114 return "unix_domain_socket_bootstrap";
Alice Wang893a9912022-10-24 10:44:09 +0000115 case SocketType::UNIX_RAW:
116 return "raw_uds";
Andrei Homescu2a298012022-06-15 01:08:54 +0000117 case SocketType::VSOCK:
118 return "vm_socket";
119 case SocketType::INET:
120 return "inet_socket";
Andrei Homescu68a55612022-08-02 01:25:15 +0000121 case SocketType::TIPC:
122 return "trusty_ipc";
Andrei Homescu2a298012022-06-15 01:08:54 +0000123 default:
124 LOG_ALWAYS_FATAL("Unknown socket type");
125 return "";
126 }
127}
128
Andrei Homescu9a9b1b42022-10-14 01:40:59 +0000129static inline size_t epochMillis() {
130 using std::chrono::duration_cast;
131 using std::chrono::milliseconds;
132 using std::chrono::seconds;
133 using std::chrono::system_clock;
134 return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
135}
136
Andrei Homescu2a298012022-06-15 01:08:54 +0000137struct BinderRpcOptions {
138 size_t numThreads = 1;
139 size_t numSessions = 1;
Steven Moreland67f85902023-03-15 01:13:49 +0000140 // right now, this can be empty, or length numSessions, where each value
141 // represents the info for the corresponding session, but we should
142 // probably switch this to be a list of sessions options so that other
143 // options can all be specified per session
144 std::vector<size_t> numIncomingConnectionsBySession = {};
Andrei Homescu2a298012022-06-15 01:08:54 +0000145 size_t numOutgoingConnections = SIZE_MAX;
146 RpcSession::FileDescriptorTransportMode clientFileDescriptorTransportMode =
147 RpcSession::FileDescriptorTransportMode::NONE;
148 std::vector<RpcSession::FileDescriptorTransportMode>
149 serverSupportedFileDescriptorTransportModes = {
150 RpcSession::FileDescriptorTransportMode::NONE};
151
152 // If true, connection failures will result in `ProcessSession::sessions` being empty
153 // instead of a fatal error.
154 bool allowConnectFailure = false;
155};
156
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000157#ifndef __TRUSTY__
Andrei Homescu2a298012022-06-15 01:08:54 +0000158static inline void writeString(android::base::borrowed_fd fd, std::string_view str) {
159 uint64_t length = str.length();
160 CHECK(android::base::WriteFully(fd, &length, sizeof(length)));
161 CHECK(android::base::WriteFully(fd, str.data(), str.length()));
162}
163
164static inline std::string readString(android::base::borrowed_fd fd) {
165 uint64_t length;
166 CHECK(android::base::ReadFully(fd, &length, sizeof(length)));
167 std::string ret(length, '\0');
168 CHECK(android::base::ReadFully(fd, ret.data(), length));
169 return ret;
170}
171
172static inline void writeToFd(android::base::borrowed_fd fd, const Parcelable& parcelable) {
173 Parcel parcel;
174 CHECK_EQ(OK, parcelable.writeToParcel(&parcel));
175 writeString(fd, std::string(reinterpret_cast<const char*>(parcel.data()), parcel.dataSize()));
176}
177
178template <typename T>
179static inline T readFromFd(android::base::borrowed_fd fd) {
180 std::string data = readString(fd);
181 Parcel parcel;
182 CHECK_EQ(OK, parcel.setData(reinterpret_cast<const uint8_t*>(data.data()), data.size()));
183 T object;
184 CHECK_EQ(OK, object.readFromParcel(&parcel));
185 return object;
186}
187
Andrei Homescuf30148c2023-03-10 00:31:45 +0000188static inline std::unique_ptr<RpcTransportCtxFactory> newTlsFactory(
Andrei Homescu2a298012022-06-15 01:08:54 +0000189 RpcSecurity rpcSecurity, std::shared_ptr<RpcCertificateVerifier> verifier = nullptr,
190 std::unique_ptr<RpcAuth> auth = nullptr) {
191 switch (rpcSecurity) {
192 case RpcSecurity::RAW:
193 return RpcTransportCtxFactoryRaw::make();
194 case RpcSecurity::TLS: {
195 if (verifier == nullptr) {
196 verifier = std::make_shared<RpcCertificateVerifierSimple>();
197 }
198 if (auth == nullptr) {
199 auth = std::make_unique<RpcAuthSelfSigned>();
200 }
201 return RpcTransportCtxFactoryTls::make(std::move(verifier), std::move(auth));
202 }
203 default:
204 LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
205 }
206}
207
208// Create an FD that returns `contents` when read.
209static inline base::unique_fd mockFileDescriptor(std::string contents) {
210 android::base::unique_fd readFd, writeFd;
211 CHECK(android::base::Pipe(&readFd, &writeFd)) << strerror(errno);
212 RpcMaybeThread([writeFd = std::move(writeFd), contents = std::move(contents)]() {
213 signal(SIGPIPE, SIG_IGN); // ignore possible SIGPIPE from the write
214 if (!WriteStringToFd(contents, writeFd)) {
215 int savedErrno = errno;
216 LOG_ALWAYS_FATAL_IF(EPIPE != savedErrno, "mockFileDescriptor write failed: %s",
217 strerror(savedErrno));
218 }
219 }).detach();
220 return readFd;
221}
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000222#endif // __TRUSTY__
Andrei Homescu2a298012022-06-15 01:08:54 +0000223
Frederick Mayleb0221d12022-10-03 23:10:53 +0000224// A threadsafe channel where writes block until the value is read.
225template <typename T>
226class HandoffChannel {
227public:
228 void write(T v) {
229 {
230 RpcMutexUniqueLock lock(mMutex);
231 // Wait for space to send.
232 mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
233 mValue.emplace(std::move(v));
234 }
235 mCvFull.notify_all();
236 RpcMutexUniqueLock lock(mMutex);
237 // Wait for it to be taken.
238 mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
239 }
240
241 T read() {
242 RpcMutexUniqueLock lock(mMutex);
243 if (!mValue.has_value()) {
244 mCvFull.wait(lock, [&]() { return mValue.has_value(); });
245 }
246 T v = std::move(mValue.value());
247 mValue.reset();
248 lock.unlock();
249 mCvEmpty.notify_all();
250 return std::move(v);
251 }
252
253private:
254 RpcMutex mMutex;
255 RpcConditionVariable mCvEmpty;
256 RpcConditionVariable mCvFull;
257 std::optional<T> mValue;
258};
259
Andrei Homescu2a298012022-06-15 01:08:54 +0000260using android::binder::Status;
261
262class MyBinderRpcSession : public BnBinderRpcSession {
263public:
264 static std::atomic<int32_t> gNum;
265
266 MyBinderRpcSession(const std::string& name) : mName(name) { gNum++; }
267 Status getName(std::string* name) override {
268 *name = mName;
269 return Status::ok();
270 }
271 ~MyBinderRpcSession() { gNum--; }
272
273private:
274 std::string mName;
275};
276
277class MyBinderRpcCallback : public BnBinderRpcCallback {
278 Status sendCallback(const std::string& value) {
279 RpcMutexUniqueLock _l(mMutex);
280 mValues.push_back(value);
281 _l.unlock();
282 mCv.notify_one();
283 return Status::ok();
284 }
285 Status sendOnewayCallback(const std::string& value) { return sendCallback(value); }
286
287public:
288 RpcMutex mMutex;
289 RpcConditionVariable mCv;
290 std::vector<std::string> mValues;
291};
292
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000293// Base class for all concrete implementations of MyBinderRpcTest.
294// Sub-classes that want to provide a full implementation should derive
295// from this class instead of MyBinderRpcTestDefault below so the compiler
296// checks that all methods are implemented.
297class MyBinderRpcTestBase : public BnBinderRpcTest {
Andrei Homescu2a298012022-06-15 01:08:54 +0000298public:
Andrei Homescu2a298012022-06-15 01:08:54 +0000299 int port = 0;
300
301 Status sendString(const std::string& str) override {
302 (void)str;
303 return Status::ok();
304 }
305 Status doubleString(const std::string& str, std::string* strstr) override {
306 *strstr = str + str;
307 return Status::ok();
308 }
309 Status getClientPort(int* out) override {
310 *out = port;
311 return Status::ok();
312 }
Andrei Homescu2a298012022-06-15 01:08:54 +0000313 Status getNullBinder(sp<IBinder>* out) override {
314 out->clear();
315 return Status::ok();
316 }
317 Status pingMe(const sp<IBinder>& binder, int32_t* out) override {
318 if (binder == nullptr) {
319 std::cout << "Received null binder!" << std::endl;
320 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
321 }
322 *out = binder->pingBinder();
323 return Status::ok();
324 }
325 Status repeatBinder(const sp<IBinder>& binder, sp<IBinder>* out) override {
326 *out = binder;
327 return Status::ok();
328 }
329 static sp<IBinder> mHeldBinder;
330 Status holdBinder(const sp<IBinder>& binder) override {
331 mHeldBinder = binder;
332 return Status::ok();
333 }
334 Status getHeldBinder(sp<IBinder>* held) override {
335 *held = mHeldBinder;
336 return Status::ok();
337 }
338 Status nestMe(const sp<IBinderRpcTest>& binder, int count) override {
339 if (count <= 0) return Status::ok();
340 return binder->nestMe(this, count - 1);
341 }
342 Status alwaysGiveMeTheSameBinder(sp<IBinder>* out) override {
343 static sp<IBinder> binder = new BBinder;
344 *out = binder;
345 return Status::ok();
346 }
347 Status openSession(const std::string& name, sp<IBinderRpcSession>* out) override {
348 *out = new MyBinderRpcSession(name);
349 return Status::ok();
350 }
351 Status getNumOpenSessions(int32_t* out) override {
352 *out = MyBinderRpcSession::gNum;
353 return Status::ok();
354 }
355
356 RpcMutex blockMutex;
357 Status lock() override {
358 blockMutex.lock();
359 return Status::ok();
360 }
361 Status unlockInMsAsync(int32_t ms) override {
362 usleep(ms * 1000);
363 blockMutex.unlock();
364 return Status::ok();
365 }
366 Status lockUnlock() override {
367 RpcMutexLockGuard _l(blockMutex);
368 return Status::ok();
369 }
370
371 Status sleepMs(int32_t ms) override {
372 usleep(ms * 1000);
373 return Status::ok();
374 }
375
376 Status sleepMsAsync(int32_t ms) override {
377 // In-process binder calls are asynchronous, but the call to this method
378 // is synchronous wrt its client. This in/out-process threading model
379 // diffentiation is a classic binder leaky abstraction (for better or
380 // worse) and is preserved here the way binder sockets plugs itself
381 // into BpBinder, as nothing is changed at the higher levels
382 // (IInterface) which result in this behavior.
383 return sleepMs(ms);
384 }
385
386 Status doCallback(const sp<IBinderRpcCallback>& callback, bool oneway, bool delayed,
387 const std::string& value) override {
388 if (callback == nullptr) {
389 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
390 }
391
392 if (delayed) {
393 RpcMaybeThread([=]() {
394 ALOGE("Executing delayed callback: '%s'", value.c_str());
395 Status status = doCallback(callback, oneway, false, value);
396 ALOGE("Delayed callback status: '%s'", status.toString8().c_str());
397 }).detach();
398 return Status::ok();
399 }
400
401 if (oneway) {
402 return callback->sendOnewayCallback(value);
403 }
404
405 return callback->sendCallback(value);
406 }
407
408 Status doCallbackAsync(const sp<IBinderRpcCallback>& callback, bool oneway, bool delayed,
409 const std::string& value) override {
410 return doCallback(callback, oneway, delayed, value);
411 }
412
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000413protected:
414 // Generic version of countBinders that works with both
415 // RpcServer and RpcServerTrusty
416 template <typename T>
417 Status countBindersImpl(const wp<T>& server, std::vector<int32_t>* out) {
418 sp<T> spServer = server.promote();
419 if (spServer == nullptr) {
Andrei Homescu2a298012022-06-15 01:08:54 +0000420 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
421 }
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000422 out->clear();
423 for (auto session : spServer->listSessions()) {
424 size_t count = session->state()->countBinders();
425 out->push_back(count);
Andrei Homescu2a298012022-06-15 01:08:54 +0000426 }
427 return Status::ok();
428 }
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000429};
Andrei Homescu2a298012022-06-15 01:08:54 +0000430
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000431// Default implementation of MyBinderRpcTest that can be used as-is
432// or derived from by classes that only want to implement a subset of
433// the unimplemented methods
434class MyBinderRpcTestDefault : public MyBinderRpcTestBase {
435public:
436 Status countBinders(std::vector<int32_t>* /*out*/) override {
437 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Andrei Homescu2a298012022-06-15 01:08:54 +0000438 }
439
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000440 Status die(bool /*cleanup*/) override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
441
442 Status scheduleShutdown() override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
443
444 Status useKernelBinderCallingId() override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
445
446 Status echoAsFile(const std::string& /*content*/,
447 android::os::ParcelFileDescriptor* /*out*/) override {
448 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Andrei Homescu2a298012022-06-15 01:08:54 +0000449 }
Frederick Mayleb0221d12022-10-03 23:10:53 +0000450
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000451 Status concatFiles(const std::vector<android::os::ParcelFileDescriptor>& /*files*/,
452 android::os::ParcelFileDescriptor* /*out*/) override {
453 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Frederick Mayleb0221d12022-10-03 23:10:53 +0000454 }
455
Andrei Homescu9d8adb12022-08-02 04:38:30 +0000456 Status blockingSendFdOneway(const android::os::ParcelFileDescriptor& /*fd*/) override {
457 return Status::fromStatusT(UNKNOWN_TRANSACTION);
458 }
459
460 Status blockingRecvFd(android::os::ParcelFileDescriptor* /*fd*/) override {
461 return Status::fromStatusT(UNKNOWN_TRANSACTION);
Frederick Mayleb0221d12022-10-03 23:10:53 +0000462 }
Frederick Mayle96872592023-03-07 14:56:15 -0800463
464 Status blockingSendIntOneway(int /*n*/) override {
465 return Status::fromStatusT(UNKNOWN_TRANSACTION);
466 }
467
468 Status blockingRecvInt(int* /*n*/) override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
Andrei Homescu2a298012022-06-15 01:08:54 +0000469};
470
471} // namespace android