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