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