blob: dc7d26491b0e9b9b2f50905a0a72a5eed256c43a [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>
25#include <aidl/IBinderRpcTest.h>
26#include <android-base/file.h>
27#include <android-base/logging.h>
28#include <android-base/properties.h>
29#include <android/binder_auto_utils.h>
30#include <android/binder_libbinder.h>
31#include <binder/Binder.h>
32#include <binder/BpBinder.h>
33#include <binder/IPCThreadState.h>
34#include <binder/IServiceManager.h>
35#include <binder/ProcessState.h>
36#include <binder/RpcServer.h>
37#include <binder/RpcSession.h>
38#include <binder/RpcThreads.h>
39#include <binder/RpcTlsTestUtils.h>
40#include <binder/RpcTlsUtils.h>
41#include <binder/RpcTransport.h>
42#include <binder/RpcTransportRaw.h>
43#include <binder/RpcTransportTls.h>
44#include <unistd.h>
45#include <string>
46#include <vector>
47
48#include <signal.h>
49
50#include "../BuildFlags.h"
51#include "../FdTrigger.h"
David Brazdil21c887c2022-09-23 12:25:18 +010052#include "../OS.h" // for testing UnixBootstrap clients
Andrei Homescu2a298012022-06-15 01:08:54 +000053#include "../RpcSocketAddress.h" // for testing preconnected clients
54#include "../RpcState.h" // for debugging
55#include "../vm_sockets.h" // for VMADDR_*
56#include "utils/Errors.h"
57
58namespace android {
59
60constexpr char kLocalInetAddress[] = "127.0.0.1";
61
62enum class RpcSecurity { RAW, TLS };
63
64static inline std::vector<RpcSecurity> RpcSecurityValues() {
65 return {RpcSecurity::RAW, RpcSecurity::TLS};
66}
67
68enum class SocketType {
69 PRECONNECTED,
70 UNIX,
David Brazdil21c887c2022-09-23 12:25:18 +010071 UNIX_BOOTSTRAP,
Andrei Homescu2a298012022-06-15 01:08:54 +000072 VSOCK,
73 INET,
74};
David Brazdil21c887c2022-09-23 12:25:18 +010075
Andrei Homescu2a298012022-06-15 01:08:54 +000076static inline std::string PrintToString(SocketType socketType) {
77 switch (socketType) {
78 case SocketType::PRECONNECTED:
79 return "preconnected_uds";
80 case SocketType::UNIX:
81 return "unix_domain_socket";
David Brazdil21c887c2022-09-23 12:25:18 +010082 case SocketType::UNIX_BOOTSTRAP:
83 return "unix_domain_socket_bootstrap";
Andrei Homescu2a298012022-06-15 01:08:54 +000084 case SocketType::VSOCK:
85 return "vm_socket";
86 case SocketType::INET:
87 return "inet_socket";
88 default:
89 LOG_ALWAYS_FATAL("Unknown socket type");
90 return "";
91 }
92}
93
Andrei Homescu9a9b1b42022-10-14 01:40:59 +000094static inline size_t epochMillis() {
95 using std::chrono::duration_cast;
96 using std::chrono::milliseconds;
97 using std::chrono::seconds;
98 using std::chrono::system_clock;
99 return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
100}
101
Andrei Homescu2a298012022-06-15 01:08:54 +0000102struct BinderRpcOptions {
103 size_t numThreads = 1;
104 size_t numSessions = 1;
105 size_t numIncomingConnections = 0;
106 size_t numOutgoingConnections = SIZE_MAX;
107 RpcSession::FileDescriptorTransportMode clientFileDescriptorTransportMode =
108 RpcSession::FileDescriptorTransportMode::NONE;
109 std::vector<RpcSession::FileDescriptorTransportMode>
110 serverSupportedFileDescriptorTransportModes = {
111 RpcSession::FileDescriptorTransportMode::NONE};
112
113 // If true, connection failures will result in `ProcessSession::sessions` being empty
114 // instead of a fatal error.
115 bool allowConnectFailure = false;
116};
117
118static inline void writeString(android::base::borrowed_fd fd, std::string_view str) {
119 uint64_t length = str.length();
120 CHECK(android::base::WriteFully(fd, &length, sizeof(length)));
121 CHECK(android::base::WriteFully(fd, str.data(), str.length()));
122}
123
124static inline std::string readString(android::base::borrowed_fd fd) {
125 uint64_t length;
126 CHECK(android::base::ReadFully(fd, &length, sizeof(length)));
127 std::string ret(length, '\0');
128 CHECK(android::base::ReadFully(fd, ret.data(), length));
129 return ret;
130}
131
132static inline void writeToFd(android::base::borrowed_fd fd, const Parcelable& parcelable) {
133 Parcel parcel;
134 CHECK_EQ(OK, parcelable.writeToParcel(&parcel));
135 writeString(fd, std::string(reinterpret_cast<const char*>(parcel.data()), parcel.dataSize()));
136}
137
138template <typename T>
139static inline T readFromFd(android::base::borrowed_fd fd) {
140 std::string data = readString(fd);
141 Parcel parcel;
142 CHECK_EQ(OK, parcel.setData(reinterpret_cast<const uint8_t*>(data.data()), data.size()));
143 T object;
144 CHECK_EQ(OK, object.readFromParcel(&parcel));
145 return object;
146}
147
148static inline std::unique_ptr<RpcTransportCtxFactory> newFactory(
149 RpcSecurity rpcSecurity, std::shared_ptr<RpcCertificateVerifier> verifier = nullptr,
150 std::unique_ptr<RpcAuth> auth = nullptr) {
151 switch (rpcSecurity) {
152 case RpcSecurity::RAW:
153 return RpcTransportCtxFactoryRaw::make();
154 case RpcSecurity::TLS: {
155 if (verifier == nullptr) {
156 verifier = std::make_shared<RpcCertificateVerifierSimple>();
157 }
158 if (auth == nullptr) {
159 auth = std::make_unique<RpcAuthSelfSigned>();
160 }
161 return RpcTransportCtxFactoryTls::make(std::move(verifier), std::move(auth));
162 }
163 default:
164 LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
165 }
166}
167
168// Create an FD that returns `contents` when read.
169static inline base::unique_fd mockFileDescriptor(std::string contents) {
170 android::base::unique_fd readFd, writeFd;
171 CHECK(android::base::Pipe(&readFd, &writeFd)) << strerror(errno);
172 RpcMaybeThread([writeFd = std::move(writeFd), contents = std::move(contents)]() {
173 signal(SIGPIPE, SIG_IGN); // ignore possible SIGPIPE from the write
174 if (!WriteStringToFd(contents, writeFd)) {
175 int savedErrno = errno;
176 LOG_ALWAYS_FATAL_IF(EPIPE != savedErrno, "mockFileDescriptor write failed: %s",
177 strerror(savedErrno));
178 }
179 }).detach();
180 return readFd;
181}
182
Frederick Mayleb0221d12022-10-03 23:10:53 +0000183// A threadsafe channel where writes block until the value is read.
184template <typename T>
185class HandoffChannel {
186public:
187 void write(T v) {
188 {
189 RpcMutexUniqueLock lock(mMutex);
190 // Wait for space to send.
191 mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
192 mValue.emplace(std::move(v));
193 }
194 mCvFull.notify_all();
195 RpcMutexUniqueLock lock(mMutex);
196 // Wait for it to be taken.
197 mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
198 }
199
200 T read() {
201 RpcMutexUniqueLock lock(mMutex);
202 if (!mValue.has_value()) {
203 mCvFull.wait(lock, [&]() { return mValue.has_value(); });
204 }
205 T v = std::move(mValue.value());
206 mValue.reset();
207 lock.unlock();
208 mCvEmpty.notify_all();
209 return std::move(v);
210 }
211
212private:
213 RpcMutex mMutex;
214 RpcConditionVariable mCvEmpty;
215 RpcConditionVariable mCvFull;
216 std::optional<T> mValue;
217};
218
Andrei Homescu2a298012022-06-15 01:08:54 +0000219using android::binder::Status;
220
221class MyBinderRpcSession : public BnBinderRpcSession {
222public:
223 static std::atomic<int32_t> gNum;
224
225 MyBinderRpcSession(const std::string& name) : mName(name) { gNum++; }
226 Status getName(std::string* name) override {
227 *name = mName;
228 return Status::ok();
229 }
230 ~MyBinderRpcSession() { gNum--; }
231
232private:
233 std::string mName;
234};
235
236class MyBinderRpcCallback : public BnBinderRpcCallback {
237 Status sendCallback(const std::string& value) {
238 RpcMutexUniqueLock _l(mMutex);
239 mValues.push_back(value);
240 _l.unlock();
241 mCv.notify_one();
242 return Status::ok();
243 }
244 Status sendOnewayCallback(const std::string& value) { return sendCallback(value); }
245
246public:
247 RpcMutex mMutex;
248 RpcConditionVariable mCv;
249 std::vector<std::string> mValues;
250};
251
252class MyBinderRpcTest : public BnBinderRpcTest {
253public:
254 wp<RpcServer> server;
255 int port = 0;
256
257 Status sendString(const std::string& str) override {
258 (void)str;
259 return Status::ok();
260 }
261 Status doubleString(const std::string& str, std::string* strstr) override {
262 *strstr = str + str;
263 return Status::ok();
264 }
265 Status getClientPort(int* out) override {
266 *out = port;
267 return Status::ok();
268 }
269 Status countBinders(std::vector<int32_t>* out) override {
270 sp<RpcServer> spServer = server.promote();
271 if (spServer == nullptr) {
272 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
273 }
274 out->clear();
275 for (auto session : spServer->listSessions()) {
276 size_t count = session->state()->countBinders();
277 out->push_back(count);
278 }
279 return Status::ok();
280 }
281 Status getNullBinder(sp<IBinder>* out) override {
282 out->clear();
283 return Status::ok();
284 }
285 Status pingMe(const sp<IBinder>& binder, int32_t* out) override {
286 if (binder == nullptr) {
287 std::cout << "Received null binder!" << std::endl;
288 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
289 }
290 *out = binder->pingBinder();
291 return Status::ok();
292 }
293 Status repeatBinder(const sp<IBinder>& binder, sp<IBinder>* out) override {
294 *out = binder;
295 return Status::ok();
296 }
297 static sp<IBinder> mHeldBinder;
298 Status holdBinder(const sp<IBinder>& binder) override {
299 mHeldBinder = binder;
300 return Status::ok();
301 }
302 Status getHeldBinder(sp<IBinder>* held) override {
303 *held = mHeldBinder;
304 return Status::ok();
305 }
306 Status nestMe(const sp<IBinderRpcTest>& binder, int count) override {
307 if (count <= 0) return Status::ok();
308 return binder->nestMe(this, count - 1);
309 }
310 Status alwaysGiveMeTheSameBinder(sp<IBinder>* out) override {
311 static sp<IBinder> binder = new BBinder;
312 *out = binder;
313 return Status::ok();
314 }
315 Status openSession(const std::string& name, sp<IBinderRpcSession>* out) override {
316 *out = new MyBinderRpcSession(name);
317 return Status::ok();
318 }
319 Status getNumOpenSessions(int32_t* out) override {
320 *out = MyBinderRpcSession::gNum;
321 return Status::ok();
322 }
323
324 RpcMutex blockMutex;
325 Status lock() override {
326 blockMutex.lock();
327 return Status::ok();
328 }
329 Status unlockInMsAsync(int32_t ms) override {
330 usleep(ms * 1000);
331 blockMutex.unlock();
332 return Status::ok();
333 }
334 Status lockUnlock() override {
335 RpcMutexLockGuard _l(blockMutex);
336 return Status::ok();
337 }
338
339 Status sleepMs(int32_t ms) override {
340 usleep(ms * 1000);
341 return Status::ok();
342 }
343
344 Status sleepMsAsync(int32_t ms) override {
345 // In-process binder calls are asynchronous, but the call to this method
346 // is synchronous wrt its client. This in/out-process threading model
347 // diffentiation is a classic binder leaky abstraction (for better or
348 // worse) and is preserved here the way binder sockets plugs itself
349 // into BpBinder, as nothing is changed at the higher levels
350 // (IInterface) which result in this behavior.
351 return sleepMs(ms);
352 }
353
354 Status doCallback(const sp<IBinderRpcCallback>& callback, bool oneway, bool delayed,
355 const std::string& value) override {
356 if (callback == nullptr) {
357 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
358 }
359
360 if (delayed) {
361 RpcMaybeThread([=]() {
362 ALOGE("Executing delayed callback: '%s'", value.c_str());
363 Status status = doCallback(callback, oneway, false, value);
364 ALOGE("Delayed callback status: '%s'", status.toString8().c_str());
365 }).detach();
366 return Status::ok();
367 }
368
369 if (oneway) {
370 return callback->sendOnewayCallback(value);
371 }
372
373 return callback->sendCallback(value);
374 }
375
376 Status doCallbackAsync(const sp<IBinderRpcCallback>& callback, bool oneway, bool delayed,
377 const std::string& value) override {
378 return doCallback(callback, oneway, delayed, value);
379 }
380
381 Status die(bool cleanup) override {
382 if (cleanup) {
383 exit(1);
384 } else {
385 _exit(1);
386 }
387 }
388
389 Status scheduleShutdown() override {
390 sp<RpcServer> strongServer = server.promote();
391 if (strongServer == nullptr) {
392 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
393 }
394 RpcMaybeThread([=] {
395 LOG_ALWAYS_FATAL_IF(!strongServer->shutdown(), "Could not shutdown");
396 }).detach();
397 return Status::ok();
398 }
399
400 Status useKernelBinderCallingId() override {
401 // this is WRONG! It does not make sense when using RPC binder, and
402 // because it is SO wrong, and so much code calls this, it should abort!
403
404 if constexpr (kEnableKernelIpc) {
405 (void)IPCThreadState::self()->getCallingPid();
406 }
407 return Status::ok();
408 }
409
410 Status echoAsFile(const std::string& content, android::os::ParcelFileDescriptor* out) override {
411 out->reset(mockFileDescriptor(content));
412 return Status::ok();
413 }
414
415 Status concatFiles(const std::vector<android::os::ParcelFileDescriptor>& files,
416 android::os::ParcelFileDescriptor* out) override {
417 std::string acc;
418 for (const auto& file : files) {
419 std::string result;
420 CHECK(android::base::ReadFdToString(file.get(), &result));
421 acc.append(result);
422 }
423 out->reset(mockFileDescriptor(acc));
424 return Status::ok();
425 }
Frederick Mayleb0221d12022-10-03 23:10:53 +0000426
427 HandoffChannel<android::base::unique_fd> mFdChannel;
428
429 Status blockingSendFdOneway(const android::os::ParcelFileDescriptor& fd) override {
430 mFdChannel.write(android::base::unique_fd(fcntl(fd.get(), F_DUPFD_CLOEXEC, 0)));
431 return Status::ok();
432 }
433
434 Status blockingRecvFd(android::os::ParcelFileDescriptor* fd) override {
435 fd->reset(mFdChannel.read());
436 return Status::ok();
437 }
Andrei Homescu2a298012022-06-15 01:08:54 +0000438};
439
440} // namespace android